New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[v2.0.0] Avoid empty imports from side-effect-free chunks #3369
Conversation
Codecov Report
@@ Coverage Diff @@
## release-2.0.0 #3369 +/- ##
=================================================
+ Coverage 94.07% 94.23% +0.15%
=================================================
Files 174 173 -1
Lines 5977 5950 -27
Branches 1768 1757 -11
=================================================
- Hits 5623 5607 -16
+ Misses 191 190 -1
+ Partials 163 153 -10
Continue to review full report at Codecov.
|
5168e11
to
dd4625a
Compare
dd4625a
to
1efe9f6
Compare
4a87438
to
da9a869
Compare
This is a huge deal for apps with a lot of dynamic imports. Would it be possible the provide this behind a flag in 1.x? Or is 2.x already close to shipping? |
Actually really close https://github.com/rollup/rollup/projects/2, the only remaining thing would be aligning on and implementing #3370 . And possibly making a call on #3343:
I spent some inspirational time today thinking that we finally should have a bot and be able to try out PRs in the REPL 😜 |
da9a869
to
b335238
Compare
Thank you for your contribution! ❤️You can try out this pull request locally via
or load it into the REPL: |
Being able to easily try out big refactors by poking at them in the REPL or even installing them into existing projects is hugely helpful in terms of being able to provide real feedback. Thank you! |
Awesome work! 👏 It seems like this would also open up #2566 for a solution, right? |
There is not really a connection, but with this change, fixing #2566 would also benefit code-splitting. |
* Respect moduleSideEffects when inlining empty imports * Make dependencies a Set * Also handle side-effect free reexports correctly without generating separate chunks * Infer side-effect free modules and hoist side-effects * Simplify some logic * Better encapsulate chunk assignment * Get rid of colouring hashes * Improve coverage * Store the build output as artifact and post an automated comment
* Respect moduleSideEffects when inlining empty imports * Make dependencies a Set * Also handle side-effect free reexports correctly without generating separate chunks * Infer side-effect free modules and hoist side-effects * Simplify some logic * Better encapsulate chunk assignment * Get rid of colouring hashes * Improve coverage * Store the build output as artifact and post an automated comment
* Respect moduleSideEffects when inlining empty imports * Make dependencies a Set * Also handle side-effect free reexports correctly without generating separate chunks * Infer side-effect free modules and hoist side-effects * Simplify some logic * Better encapsulate chunk assignment * Get rid of colouring hashes * Improve coverage * Store the build output as artifact and post an automated comment
* Respect moduleSideEffects when inlining empty imports * Make dependencies a Set * Also handle side-effect free reexports correctly without generating separate chunks * Infer side-effect free modules and hoist side-effects * Simplify some logic * Better encapsulate chunk assignment * Get rid of colouring hashes * Improve coverage * Store the build output as artifact and post an automated comment
* Respect moduleSideEffects when inlining empty imports * Make dependencies a Set * Also handle side-effect free reexports correctly without generating separate chunks * Infer side-effect free modules and hoist side-effects * Simplify some logic * Better encapsulate chunk assignment * Get rid of colouring hashes * Improve coverage * Store the build output as artifact and post an automated comment
* Respect moduleSideEffects when inlining empty imports * Make dependencies a Set * Also handle side-effect free reexports correctly without generating separate chunks * Infer side-effect free modules and hoist side-effects * Simplify some logic * Better encapsulate chunk assignment * Get rid of colouring hashes * Improve coverage * Store the build output as artifact and post an automated comment
This PR contains:
Are tests included?
Breaking Changes?
List any relevant issue numbers:
Resolves #3359
Resolves #3109
Resolves #3057
Description
Originally the goal with this PR was to just suppress empty imports from chunks if
moduleSideEffects
isfalse
. However as it turned out, it was possible to extend this beyond themoduleSideEffects
flag by using the existing tree-shaking mechanics to infer this flag for modules for which it was not explicitly set tofalse
; moreover, Rollup will also generate fewer chunks in many situations.To do this right, I implemented this on module level, not on chunk level. This means that after tree-shaking, each "empty" dependency (i.e. import where no bindings are actually imported) of a module is tested for side-effects and
moduleSideEffects
isfalse
for this dependencymoduleSideEffects
istrue
but no side-effects can be found inside the moduleThis happens BEFORE chunks are generated, which means that after this PR, more efficient chunks will be generated! As an example, consider the following:
If you run this in the REPL, you will get three chunks with an empty import from the
main2
chunk to the shared chunk–even though the shared chunk does not have side-effects: https://rollupjs.org/repl/?version=1.31.0&shareable=JTdCJTIybW9kdWxlcyUyMiUzQSU1QiU3QiUyMm5hbWUlMjIlM0ElMjJtYWluLmpzJTIyJTJDJTIyY29kZSUyMiUzQSUyMmltcG9ydCUyMGRlcCUyMGZyb20lMjAnLiUyRmRlcC5qcyclM0IlNUNuZGVwKCklM0IlMjIlMkMlMjJpc0VudHJ5JTIyJTNBdHJ1ZSU3RCUyQyU3QiUyMm5hbWUlMjIlM0ElMjJtYWluMi5qcyUyMiUyQyUyMmNvZGUlMjIlM0ElMjJpbXBvcnQlMjBkZXAlMjBmcm9tJTIwJy4lMkZkZXAuanMnJTNCJTVDbmNvbnNvbGUubG9nKCdtYWluMicpJTNCJTIyJTJDJTIyaXNFbnRyeSUyMiUzQXRydWUlN0QlMkMlN0IlMjJuYW1lJTIyJTNBJTIyZGVwLmpzJTIyJTJDJTIyY29kZSUyMiUzQSUyMmV4cG9ydCUyMGRlZmF1bHQlMjBmdW5jdGlvbiUyMG9ubHlVc2VkQnlPbmUoKSUyMCU3QiU1Q24lNUN0Y29uc29sZS5sb2coJ0hlbGxvJyklM0IlNUNuJTdEJTIyJTJDJTIyaXNFbnRyeSUyMiUzQWZhbHNlJTdEJTVEJTJDJTIyb3B0aW9ucyUyMiUzQSU3QiUyMmZvcm1hdCUyMiUzQSUyMmVzbSUyMiUyQyUyMm5hbWUlMjIlM0ElMjJteUJ1bmRsZSUyMiUyQyUyMmFtZCUyMiUzQSU3QiUyMmlkJTIyJTNBJTIyJTIyJTdEJTJDJTIyZ2xvYmFscyUyMiUzQSU3QiU3RCU3RCUyQyUyMmV4YW1wbGUlMjIlM0FudWxsJTdEWith this PR, you will instead just get the following two chunks:
You can check this out here: https://rollupjs.org/repl/?circleci=9330&shareable=JTdCJTIybW9kdWxlcyUyMiUzQSU1QiU3QiUyMm5hbWUlMjIlM0ElMjJtYWluLmpzJTIyJTJDJTIyY29kZSUyMiUzQSUyMmltcG9ydCUyMGRlcCUyMGZyb20lMjAnLiUyRmRlcC5qcyclM0IlNUNuZGVwKCklM0IlMjIlMkMlMjJpc0VudHJ5JTIyJTNBdHJ1ZSU3RCUyQyU3QiUyMm5hbWUlMjIlM0ElMjJtYWluMi5qcyUyMiUyQyUyMmNvZGUlMjIlM0ElMjJpbXBvcnQlMjBkZXAlMjBmcm9tJTIwJy4lMkZkZXAuanMnJTNCJTVDbmNvbnNvbGUubG9nKCdtYWluMicpJTNCJTIyJTJDJTIyaXNFbnRyeSUyMiUzQXRydWUlN0QlMkMlN0IlMjJuYW1lJTIyJTNBJTIyZGVwLmpzJTIyJTJDJTIyY29kZSUyMiUzQSUyMmV4cG9ydCUyMGRlZmF1bHQlMjBmdW5jdGlvbiUyMG9ubHlVc2VkQnlPbmUoKSUyMCU3QiU1Q24lNUN0Y29uc29sZS5sb2coJ0hlbGxvJyklM0IlNUNuJTdEJTIyJTJDJTIyaXNFbnRyeSUyMiUzQWZhbHNlJTdEJTVEJTJDJTIyb3B0aW9ucyUyMiUzQSU3QiUyMmZvcm1hdCUyMiUzQSUyMmVzbSUyMiUyQyUyMm5hbWUlMjIlM0ElMjJteUJ1bmRsZSUyMiUyQyUyMmFtZCUyMiUzQSU3QiUyMmlkJTIyJTNBJTIyJTIyJTdEJTJDJTIyZ2xvYmFscyUyMiUzQSU3QiU3RCU3RCUyQyUyMmV4YW1wbGUlMjIlM0FudWxsJTdE
This means you will not only get fewer chunks but the second chunk will also avoid loading quite a bit of maybe-not-dead-but-definitely-not-needed code.
Now assume that
dep.js
itself has a side-effectful dependency, for instance an external import:Then you will STILL get two chunks, but the side-effect import will be hoisted to both chunks:
I think this is a great improvement for everyone and the first step to actually fixing many ordering issues we can currently have with code-splitting without creating endless amounts of chunks as side-effect-free modules can be moved around rather safely (not done in this PR yet, though).
I have marked this as "BREAKING" because with this change, side-effect-free modules will no longer appear as part of any chunk in the generated bundle object. Previously, they would always appear to be assigned to some chunk. I am not sure if there are tools that analyze tree-shaking quality that depend on all modules being mentioned in the output.