question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Rollup not tree-shaking from "d3" package

See original GitHub issue

When 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:closed
  • Created 7 years ago
  • Comments:18 (6 by maintainers)

github_iconTop GitHub Comments

5reactions
Rich-Harriscommented, Mar 13, 2017

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:

// node_modules/tool/index.js
export { default as foo } from './foo.js'; /*esm pure*/
export { default as bar } from './bar.js'; /*esm pure*/
export { default as baz } from './baz.js'; /*esm pure*/

// my-custom-build.js
export { foo } from 'tool'; // bar and baz are not followed

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.

3reactions
currancommented, Mar 17, 2017

However, why are we talking about introducing a custom annotation instead of teaching library authors to write modules without side-effects?

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:

export {
  selectWithTransition as select,
  selectAllWithTransition as selectAll
} from "d3-transition";
Read more comments on GitHub >

github_iconTop Results From Across the Web

Developers - Rollup not tree-shaking from "d3" package -
When creating a custom bundle with ES6 modules from the d3 package, Rollup includes unnecessary JavaScript in the build. In the original example...
Read more >
Tree Shaking - webpack
Tree shaking is a term commonly used in the JavaScript context for ... The name and concept have been popularized by the ES2015...
Read more >
rollup.js
During this step, Rollup will build the module graph and perform tree-shaking, but will not generate any output. On a bundle object, you...
Read more >
Rollup, not tree-shaking properly, providing full bundle
I'm having an issue tree-shaking with rollup. I exported a new function min that does basically nothing from my utils/index.js module.
Read more >
Does my bundle look big in this? - LogRocket Blog
Rollup has determined the bare minimum of imports the code needs to execute with a process known as tree shaking. import React from...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found