Rollup not tree-shaking from "d3" package
See original GitHub issueWhen creating a custom bundle with ES6 modules from the d3
package, Rollup includes unnecessary JavaScript in the build.
In the original example D3 Custom Bundle, the non-minified bundle d3.js
is 23.4 Kb, using the following source:
export {
event,
select,
selectAll
} from "d3-selection";
In the fork I made D3 Custom Bundle from “d3” package, the non-minified bundle d3.js
is 185.7 Kb, using the following source:
export {
event,
select,
selectAll
} from "d3";
My understanding is that the resulting bundle size should be the same, regardless of whether the modules are exported from packages “d3” or “d3-selection”.
This is with package “d3” at version 4.7.2 and Rollup version 0.41.
I thought this might be related to this change which makes exports implicit, which affects versions 4.4.2 and above. As an experiment, I tried the same build using version 4.4.1, which is the most recent version that uses explicit exports. The same problem appears, the resulting non-minified bundle is 181.3 Kb.
FWIW, I also tried setting the Rollup NPM plugin flags explicitly, to try to get it to use module
only, like this plugins: [node({module: true, jsnext: false, main: false})],
, to no avail:
Also possibly related to StackOverflow: Webpack 2 Not Tree Shaking D3.js Properly.
I’m not sure if the source of this issue lies with the D3 packages, or with Rollup. I went through all the issues currently in Rollup, and didn’t see anything that might be a duplicate of this.
/cc @Rich-Harris
Issue Analytics
- State:
- Created 7 years ago
- Comments:18 (6 by maintainers)
Top GitHub Comments
Yeah, there’s no silver bullet. I’ve resisted hints thus far for the reasons you described, but it might not be the worst thing to throw into the mix.
If we did do something along those lines I’d prefer it not to be tool-specific, so that Webpack users could benefit from it too. (CC @TheLarkInn — Hi Sean, we’re talking about adding a comment next to
import
declarations so that bundlers can ignore unused submodules from an ‘index module’ without having to worry about missing side-effects.) Maybe something like this:I’ve been working on a new approach to tree-shaking in a separate Rollup branch, but unfortunately I got sidetracked by other projects and haven’t been able to get it into shape, and it’s probably diverged quite far from
master
now. But if it eventually pans out it should do a much better job of eliminating false positives. Hopefully I can get back on that soon.I strongly agree with this sentiment. Can we add an
assumePure
flag to Rollup and Webpack and banish this whole notion of conservatively including modules because they might have side effects? Any function might have a side effect. Trying to detect side effects seems like a bad road to go down, especially if detecting whether a module has side effects turns out to be undecidable like the Halting Problem, which I believe it is.Then we’d be left with the issue of how to tell the bundler to make exceptions for modules that do have side effects, like d3-transition. I’d be more than happy to put a list of modules with intentional side effects to “hard-include” in my Rollup or Webpack configuration, because modules with intentional side effects are few and far between (as far as I’ve seen at least - this would be interesting to get real data on).
Even in the case of d3-transition, the side effect is surprising. Maybe there’s a little hidden dependency 🌶 going on there. It would be great if the side effect could be eliminated. I’m not sure what form this would take, nor have I thought through if it’s even possible to get the same features without the side effect of mutating the selection prototype, but maybe it could look something like this in our custom D3 bundle index: