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
Tree-shaking rxjs 6 produces left-over non-exported functions #2415
Comments
Thanks for digging into this. TypeScript helpers are indeed nasty as they rely on mutations a lot which our analysis just gives up on as you have noticed (with the As you already did some digging, if you could put the gist of your findings into a REPL link that contains the helper code in question and how it is used in an example where you would expect tree-shaking, this would be a huge help as this could give us an important real-world ready-to-use test-case once we implement the new logic. |
Try this example. Out of interest, what kind of "new logic" would solve this problem? Something like traversing further into the variable declarator and checking what it really modifies? |
Thanks a lot! The rough issue is that if a variable has been marked as "reassigned", the current logic becomes very conservative about further modifications. The new approach would be akin to calculating a "single static assignment form", which means modifications are treated as definitions of new variables with different values. We would then run the tree-shaking on the new form to determine which modifications do not have effects because their resulting variables are not used. However with your example, we can figure out if there are ways to extend the existing logic as well, which could provide a solution in a shorter frame of time. |
I've noticed something similar when importing |
Hello again. @lukastaegert when can we expect the new algorithm to be implemented and thus this issue fixed? I am starting a new project and am facing a bundler choice decision. If this would be fixed in the next 2-3 months I would definitely stay with rollup (I am a fan ^^), but if not, I will have to use something I like less. |
@lukastaegert Does Rollup support the Webpack
The effectiveness of
Webpack and Parcel take advantage of this package hint. |
As rollup does not read package.json files, this would be needed to be implemented somehow in rollup-plugin-node-resolve but there is no API for this in rollup yet. As for the algorithmic rewrite, 2-3 months will probably not be enough but adding support for |
Created #2593 to track |
@lukastaegert There's a marked improvement in rollup bundling now that it supports Building https://github.com/mischnic/tree-shaking-example with:
produces:
@43081j The tree shakability of rxjs is being improved in ReactiveX/rxjs#4769 thanks to @filipesilva. /cc @mischnic |
That is fantastic! Hope the rxjs fix lands there fast and that it will all work correctly now, that would mean much simpler build step for production. |
@filipesilva Will the tree shaking fix in PR ReactiveX/rxjs#4769 introduce pure annotations into
Comparison of
|
Hmmm I imagine that's actually a bug in the build setup for RxJs. I should have a look at that. |
I've updated https://github.com/mischnic/tree-shaking-example to include rxjs (waiting for that rxjs PR...) and react-icons (which parcel has/had issues bundling). I've also added coverage reports for all these cases (though 100% is not always achievable). |
@mischnic Angular relies a LOT of tree shaking to reduce our bundle size. You can try If you also want to just check if libraries have side effects without importing anything specific I recommend https://github.com/filipesilva/check-side-effects. This is what I used to detect them in the RxJS and the equivalent Angular PR (angular/angular#29329). |
@mischnic Regarding the newly added https://github.com/mischnic/tree-shaking-example result:
Webpack replaces To compare apples with apples apply this patch: --- a/rollup.config.js
+++ b/rollup.config.js
@@ -15,7 +15,15 @@ export default [
exclude: "node_modules/**"
}),
commonjs(),
- terser({ sourcemap: false, toplevel: true })
+ terser({
+ compress: {
+ global_defs: {
+ "process.env.NODE_ENV": "production",
+ },
+ },
+ sourcemap: false,
+ toplevel: true,
+ })
],
output: [{ file: `rollup/${libName}.js`, format: "cjs" }]
} to get this result:
Webpack v4 bundles are generally 1.5 KB larger than the rollup equivalent because of its fixed bootstrapping code. |
Thanks, updated.
This comparison can't perfectly compare apples to apples of course... |
@filipesilva afaict But since the generated
I'm not familiar with the use of the |
Yes, we use it a lot on Angular packages but it's not a standard. It's part of what we call Angular Package Format (APF, doc here). It's mostly just guidelines on how Angular libs that distribute multiple formats, and different entry points, and should support different consumers should be packaged. |
@filipesilva I see. So if Angular is the only consumer of the not-pure-annotated |
Right now, yes. We'd like it to be more ergonomic to use the es2015 bundles though... |
Hey folks. This is a saved-form message, but rest assured we mean every word. The Rollup team is attempting to clean up the Issues backlog in the hopes that the active and still-needed, still-relevant issues bubble up to the surface. With that, we're closing issues that have been open for an eon or two, and have gone stale like pirate hard-tack without activity. We really appreciate the folks have taken the time to open and comment on this issue. Please don't confuse this closure with us not caring or dismissing your issue, feature request, discussion, or report. The issue will still be here, just in a closed state. If the issue pertains to a bug, please re-test for the bug on the latest version of Rollup and if present, please tag @shellscape and request a re-open, and we'll be happy to oblige. |
@shellscape Please reopen this issue as the bug still persists. To replicate the issue, do the following:
Expected behavior: |
@lukastaegert when you have a moment please evaluate this one given the repro above. I can confirm the behavior, but I don't know enough to know if that's intended, or if that's the cause of something else outside of rollup going sideways. |
I don't believe this is intended, as even my WebStorm hints the unused items. Also, other bundlers with tree shaking omit unused code. |
Rollup can only tree shake code that is conducive to it. AFAICT the tree shaking fix in the See: ReactiveX/rxjs#4953 ReactiveX/rxjs#4769. As a workaround in the meantime you could probably use the rollup flag @filipesilva Correct me if I'm wrong. |
The unused variables are part of the code because Rollup cannot determine conclusively that the functions that are called to generate them are side-effect free. I do not expect in a short time frame for Rollup to properly understand the mutating way TS helper wrappers work unless we hard code them into Rollup, which would be brittle. @kzc is right and his suggestion will help. For more dramatic results, you can add But you do not need any of this if you use |
Interesting, will give it a shot later, thanks for a workaround tip @kzc @lukastaegert. |
Given the following:
And config:
The
rxjs/operators
import resolves torxjs/_esm5/operators/index.js
which looks something like:We end up with a
214K
bundle, for 9 lines of code and two imports.Looking at the bundle, it seems unexported functions/classes are somehow kept.
Take this operator for example.
In our bundle:
What is going on here? Is this rx's fault or rollup's or mine?
How do we possibly end up with classes in our bundle which were never even exported?
Edit
rxjs depends on
tslib
which seems to be the culprit for marking everything as having side effectsI stepped through rollup's traversal for a while to see which node returned true for
hasEffects
. It turns out to be this helper from TypeScript's tslib helpers.The
CallExpression
here goes through the usual checks (hasEffects
):CallExpression -> callee (Identifier) -> variable (LocalVariable)
Where the
LocalVariable
is this. BecauseisReassigned
is true on that, everything which uses this helper ends up being included.Any idea how to combat this? This is depended on by rx, not my code. Is there a way maybe to let rollup know we don't care about it?
The text was updated successfully, but these errors were encountered: