How to import ES2015 modules functions selectively

2020-03-01 17:09发布

问题:

I'm getting started with Rollup and D3 version 4, which is written in ES2015 modules. I've written a some code using the traditional D3 namespace "d3". Now I want to create a custom bundle using Rollup. I want to using tree-shaking, because I'm probably only using about half the functions in d3, and I want to keep things as light as possible.

I'm clear that I can import functions selectively, e.g.:

import {scaleLinear} from "d3-scale";
import {
      event,
      select,
      selectAll
} from "d3-selection";

That is going to get very verbose very fast, because half of d3 is a lot of functions. I can live with that. The bigger problem is that it also would require completely rewriting all my function identifiers without a namespace. I don't much care for that, because I prefer to namespace library code.

I understand that I can import all of the module:

import * as d3 from "d3";

which preserves the d3 object namespace, which is good for my code organization. But then Rollup can't tree-shake the unused functions out of the bundle.

What I'm dreaming of is something like:

import {
      event,
      select,
      selectAll
} as d3 from "d3-selection";

but that sort of feature/syntax doesn't seem to exist in the spec. How can I both selectively target individual parts of a module, and preserve namespacing during an import?

回答1:

You need a re-exporting module for that:

export {
      event,
      select,
      selectAll
} from "d3-selection";

import * as d3 from './d3';


回答2:

that sort of feature/syntax doesn't seem to exist in the spec

No, this is indeed impossible. According to the spec, once a module is included, the whole module is evaluated and included, so there's no need for a partial inclusion. A namespace object always allows access to all properties of the module.

But then Rollup can't tree-shake the unused functions out of the bundle.

That would be Rollup's fault, but actually it is able to statically analyse the code for usages of the namespace object, and figure out which properties are used. This optimisation might need to bail out if the object is used for anything that is not a dotted member access, but in general it's quite possible. If it's not working as expected, you might want to file a bug report (see also troubleshooting).