-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
Rollup Version
4.50.0
Operating System (or Browser)
MacOS / Chrome
Node Version (if applicable)
No response
Link To Reproduction
Expected Behaviour
Module ids that are not handled by manualChunks (returned as undefined or null) should not be bundled together with other manualChunks and instead be processed by Rollup as if there was no manualChunks.
Actual Behaviour
A module id that is not handled by manualChunks (returned as undefined or null) gets bundled together to the first manualChunk encountered (alphabetically), when the module in question is imported by multiple manualChunks.
In the repro, the entry1-task.js, entry2-task.js, and entry3-task.js share common utils imports, but all the utils code ends up in entry1-[hash].js
This leads to 2 issues:
- The first (alphabetically) manualChunk that imports a non manualChunk module that is also imported by other manualChunks will get bigger. This can affect multiple bundles in a non repro setup. This is represented by the
entry1-[hash].jsbundle in the repro. - The manualChunks static import graph becomes inaccurate (which can change the dynamic imports graph in complex setups). In the repro, every time
entry2-[hash].jsandentry3-[hash].jsare to be requested, the app will also requestentry1-[hash].js, even though they are not requesting the originalentry1-task.jsorentry1-onClick.jsexports, just the utils in common.
Note: in the repro, if you remove manualChunks you will notice that Rollup is smart enough to create two utils bundles based on the imports graph instead of 3, because
entry3-task.jsdoes not import fromutils1.js. Here it's a simplified example, but this shows that the bundler is smarter at bundling non manualChunk modules when they're not merged with other manualChunks.
This issue is particularly bad in qwik, where we first split the developers code into the smallest possible segments and emit them, and then group the emitted segments that share a common entry point together (using manualChunks). As a result qwik has ~10x more bundles than most other frameworks and we can be surgical about what to preload and when. But for that we need to leverage the static and dynamic import graphs to know which bundles to preload ahead of time or be able to reprioritize them on user interaction. When some bundles are bigger than expected and the graph is incorrect, user interactions are delayed even more on bad network conditions. I also explain the issue here with a qwik repro: QwikDev/qwik#7882.
The problem comes from generateChunks -> getChunkAssignments -> getChunkDefinitionsFromManualChunks -> addStaticDependenciesToManualChunk -> if (!(dependency instanceof ExternalModule || modulesInManualChunks.has(dependency))) { modulesToHandle.add(dependency) }.
This can be fixed by removing the addStaticDependenciesToManualChunk logic. I'm not sure if that would be a breaking change though. I assume most projects use manualChunks for code-splitting purposes. Could it be we're the only ones to leverage manualChunks to group files together and that's why it doesn't work for us 😄?