Webpack runtime conflicts, 'runtimeChunk' and missing dependencies

Hello

We’re struggling with Webpack for a Bitbucket app. I’m not yet 100% sure where to start.

The high level issue:

  1. When the app is installed on its own or with many other apps, it seems fine.
  2. However, the app breaks other apps, like Crucible Review Hook for Bitbucket

From my debugging, it looks like the apps seem to clash on the webpack ‘runtime’ things.
I’ve noticed:

  1. Bitbucket ships a webpack runtime
  2. Our Javascript bundled with webpack and the Atlassian Client-Side Webpack pluging also ships / includes a webpack runtime.
  3. Looks like these two runtimes the stop over each other and module definitions get messed up.

Ok: We had similar issues with another app. There we disabled the ‘runtimeChunking’. I tried that again, but this has some unexpected side effect in the generated wr-webpack.xml file.

Before:

{
optimization: {
   runtimeChunk: 'single',
}
}

Then the generated wr-webpack.xml does have the required dependencies, the aui-select in this case.

  <web-resource key="split_codeowners">
    <transformation extension="js">
      <transformer key="jsI18n"/>
    </transformation>
    <dependency>com.atlassian.plugins.atlassian-plugins-webresource-plugin:context-path</dependency>
    <dependency>com.atlassian.auiplugin:aui-flag</dependency>
    <dependency>com.atlassian.bitbucket.server.bitbucket-web-api:navbuilder</dependency>
    <dependency>com.atlassian.bitbucket.state.bitbucket-web-api:state</dependency>
    <dependency>com.atlassian.bitbucket.server.bitbucket-web-api:server</dependency>
    <dependency>com.atlassian.bitbucket.events.bitbucket-web-api:events</dependency>
    <dependency>com.atlassian.auiplugin:aui-select</dependency>
    <resource type="download" name="codeowners.js" location="js/codeowners.js"/>
  </web-resource>

However, when I disable the chunking with runtimeChunk: false, then the aui-select dependency is simply omitted:

    <web-resource key="entrypoint-codeowners">
    <transformation extension="js">
      <transformer key="jsI18n"/>
    </transformation>
    <context>bitbucket.page.compare</context>
    <context>bitbucket.page.pullRequest.view</context>
    <context>bitbucket.page.pullRequest.detail</context>
    <dependency>com.atlassian.plugins.atlassian-plugins-webresource-plugin:context-path</dependency>
    <dependency>com.atlassian.auiplugin:aui-flag</dependency>
    <dependency>com.atlassian.bitbucket.server.bitbucket-web-api:navbuilder</dependency>
    <dependency>com.atlassian.bitbucket.server.bitbucket-web-api:server</dependency>
    <resource type="download" name="codeowners.js" location="js/codeowners.js"/>
  </web-resource>

So, I am stuck:

  • Is the app supposed to ship with the webpack runtime or now? How do I avoid conflicts with other apps with the webpack module resolution?
  • Why does the runtimeChunk influence the imports in the generated wr-webpack.xml ? Is there a way to fix that?
2 Likes

I didn’t look at your post in depth, but Webpack bundles can collide with other resources on the page if you (and they) do not have their own unique jsonp function defined for their own chunks.

If you don’t already have this in your webpack config, try putting it there. Config below is for 5.x. I believe it is named “jsonpFunction” if you’re still using webpack 4.x.

output: {
    /* ... */
    chunkLoadingGlobal: 'myUniqueName'
}

For what it’s worth, I’m using runtimeChunk: single successfully on other host apps.

1 Like

Thanks, that seems to work.

Still puzzled why the disabling the runtimeChunk skips the dependencies. But using the unique name seems to fix the issue, so I’ll go with that.

It’s not you, it’s a bug in the WRM Webpack plugin. We tried to make it compatible with Webpack v4 and v5 to ease migrations, but with this extra complexity v5 is a little finnicky+buggy. Internall v4 and v5 are very different and we need to first refactor the plugin to fix the bug, we’ll be dropping v4 support in the next major version of the plugin to unblock the refactor. We’re aware, we feel the same pain too, sorry about this.

2 Likes

Can we get some more info about this? We have an app that was developed with the “legacy” kind of resources, and now we’re replacing most of that with TS code. We still need to import some existing resources and we’re declaring them with providedDependencies. The weird thing is that sometimes they are added as dependencies, sometimes they are not. I can’t figure out when and why. I spent hours even to figure out that it’s happening.

I tried updating to version 6.0.0, but that still has the bug. Any hints about what I could try?

1 Like

I’m so sorry, I have never seen this reported before. I know it’s not always quick and easy, but could you please if possible create a reproduction repository on Bitbucket or GitHub or something?

We recently released 6.0.0 of WRM webpack plugin dropping support for v4 of Webpack. We haven’t made any noise about it, because we’re not sure we’ve fixed everything. We had to get what we had out the door though. If it does solve your problems I’d love to hear it.

I only have complete shot in the dark ideas for you; does it happen to be consistent when rerunning production builds? is optimization.runtimeChunk to single? I assume there’s nothing that could potentially be rewriting the symbols before WRM webpack plugin processes the files to add the provided dependencies? Can you try doing import "wr!atlassian.plugin.key:web-resource-key"?

Our public issue tracker is here if that ever helps, but also where you can report bugs if you want. I appreciate every bug report, even if it’s hard to build a reproduction repository or steps.

Thanks for taking the time to report it here!

Hello Michael, awesome that you replied so promptly!

I just reported SPFE-1065 and I included an archive with a test project that, at least for me, reproduces the bug(s).

Yes, I noticed and tried it while I was debugging the issue. My problem still happens with 6.0.0, although I originally discovered it with 5.2.11.

As far as I can tell, it happens consistently with production builds, which do use runtimeChunk: "single".

(We have been running dev builds without that flag for a while, and they mostly seem to load the correct dependencies, but I didn’t actually check very closely what those were doing. The reason for having a single runtime chunk is that our app does dashboard items, and we have a lot of entry points that can be loaded at the same time, one for each gadget type. That was at least causing warnings in the dev builds, but we weren’t paying much attention to that part.)

I don’t actually understand enough about how that part works to answer this properly. We do use Babel and Typescript, so maybe one of those is doing something like that? Hopefully the test project I attached to the issue can help.

Yes, I tried that. (Actually, I tried it with wr-dependency!...; not sure if wr!... is just an abbreviation or is supposed to mean something else. Just wr! did not work.)

There is an example in the archive I provided. If I use that syntax, then the proper <dependency> entries are created in in the XML descriptor, but the generated JS code does not seem to actually require the resource.

(In my full project, before stripping it down for this example, it didn’t work. The “imported” value was actually a function instead of what the legacy resource provided. I tried calling it, but it crashed. Not sure what it’s supposed to be.)

I didn’t know about that project, and even if I did I tend to ignore Atlassian issue trackers since most reported issues are just ignored. Even in SPFE I see there are three issues from 2022 and one from 2021 with Major or Critical priority that are still in Needs Triage status… :face_with_peeking_eye:

But given your prompt reply here I created an issue. We can continue the discussion in comments there if you think it’s better than doing it here.

1 Like

Thank you so much!

No, I just made a mistake, sorry.

Sorry, just to clarify (before I misunderstand), did you try both require() and wr-dependency! together?

I reopened them to make sure they are actually fixed. It might be a surprise to you, but the public facing issues my team and I are solving are often 5, 10, 15, 20 years old as DC is now focused on stability more than ever before. Sometimes the old problems become worse, or they become easier to solve, occasionally just no longer relevant.

It’s unfortunate it’s not obvious that we do fix many old tickets, I would like to give people the satisfaction and the feeling it’s been taking on board. If you have any suggestions here, I’m happy to hear them!

I tried import LegacyStuff from "name/used/in/provided/dependencies and import LegacyStuff from "wr-dependency!plugin-key:resource-key". (On separate occasions, not both at the same time in the same file.)

There should be an example of each in the archive I attached to the issue, to make them easy to compare.

To be clear, we don’t use require anywhere in the Webpack-compiled code, just import.

(The legacy code uses define("module", ["dependencies"]...), but those dependencies are handled manually.)

Well now I’m in the uncomfortable position of being very happy with your team in particular (for working on these issues now) while still being annoyed at Atlassian in general (for not working on them until now) :disappointed_relieved:

Anyway, we aren’t solving our bugs as soon as they get in the issue tracker, either, so sorry for being snippy earlier, and thanks again for looking into this :smile:

Yes, that is tricky now that you mention it, and I don’t really know a good way to communicate it. Maybe a dashboard showing the open issues going down? (On a completely unrelated subject, our app, which we can’t update until we find a solution for the bug we’re discussing, does awesome dashboards when it works :wink:)

I guess it will become obvious when you finish fixing all of them :slight_smile: