-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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 with sideEffects false #1241
Comments
AFAIK I agree that your interpretation sounds reasonable. This is also along the lines of what I was thinking in that past thread here:
However, I'm not aware of any other bundler that interprets the |
Sounds like this is similar to the What unsafe assumption do rollup, parcel, webpack make that makes them ignore that assignment. Is it that property assignments are considered side-effect free? Would you be willing to optionally enable such an assumption? As seen from your example, this affects the bundle size for icon libraries, component libraries etc (often?). I have another case besides this one with @primer/components. Is there already a way to leverage |
My 2c: Rather than implementing a safer-but-not-the-norm version of how |
The problem with this is that from what I understand, it's extremely tricky to build and would be a big step up in complexity for esbuild's tree shaking implementation. You basically have to model the evolution of the object shape as it's constructed and track all references to the object to determine whether or not an assignment has side effects. By comparison, the connected component approach would be simple to implement and (at least to me) seems like it would be relatively robust. It would only work under the assumption that property assignments don't have side effects given From the library authoring end, the most straightforward way to allow code with possible side effects to be tree shaken within a single file with the current version of esbuild is to use a pure annotation like this: export var ChecklistIcon = /* @__PURE__ */ (() => {
function ChecklistIcon(props) {}
ChecklistIcon.defaultProps = {}
return ChecklistIcon
})() This is something that has to be done on the library authoring end, however. It cannot be done on the library consumption end. |
That does seem significantly more complex. It's kinda crazy that we have to rely on this for dead code elimination! In an ideal world we'd push library authors to split code into little ESMs. Icon and Component libraries should for sure be doing this. Thanks for your efforts! |
Dropping objects/functions/classes without consideration to all their references would lead to incorrect results. Pure annotated calls were invented by uglify and embraced by babel and webpack to get around the inability at the time to eliminate unused As for the webpack |
It appears webpack will indeed prune "unused" statements from side effect-free files, even statements with obvious side effects such as I've created a simple repo to demonstrate this: https://github.com/rtsao/side-effects-statements-test Obviously there is not a clear specification for the I'm attempting to migrate some apps from webpack to esbuild and this difference in behavior is a bit of a hurdle at the moment. |
Here's a simplified version of @rtsao's example. It shows the unwanted retention of side effect code within non-entry-point Although webpack is not shown here, rollup and webpack produce the same result for this example. Rollup is just easier to use for illustrative purposes.
Consider Note: the example was revised to demonstrate the "all or nothing" nature of side effect retention in non-entry-point |
Would be great to know how you see the priority of this - not trying to push, just trying to understand so I can decide how to work around it. I would try to contribute, but understanding the tree shaking logic seems more work than I'd like to sign up for right now ;) |
This not working is kind of a big deal for me, it causes esbuild to produce larger bundles, or even outright fail to bundle, for example when importing an isomorphic export out of a module that also has some Node-only exports. |
Also both webpack and rollup tree-shake unused exports from packages having |
I have an esbuild plugin for node modules polyfill. And I'm also having a similar issue. When a user imports a single fn from a module, I need to give the full contents of the module to esbuild and esbuild doesn't tree shake the code so full module gets added in the final bundle. In this pr, only |
I'm trying to diagnose why this package:
https://www.npmjs.com/package/@primer/octicons-react
Which contains the required magical incantation of
sideEffects: false
:https://github.com/primer/octicons/blob/main/lib/octicons_react/package.json#L10
With usage like this:
Ends up with all the exports from
@primer/octicons-react
in the bundle. I'm guessing it's because of the assignments todefaultProps
, but shouldn'tsideEffects: false
trigger ignoring those?Sample repository here: https://github.com/daaku/esbuild-octicons-shake-test
The text was updated successfully, but these errors were encountered: