I've got a file d3.custom.build.js
like this (simplified):
import { range } from 'd3-array';
import { select, selectAll, event } from 'd3-selection';
import { transition } from 'd3-transition';
export default {
range,
select,
selectAll,
event,
transition
};
And a rollup.config.js
like this:
import nodeResolve from 'rollup-plugin-node-resolve';
export default {
entry: './js/vendor/d3-custom-build.js',
dest: './js/vendor/d3-custom-built.js',
format: 'iife',
globals: {
d3: 'd3'
},
moduleId: 'd3',
moduleName: 'd3',
plugins: [nodeResolve({ jsnext: true })]
};
I want to export to a plain old browser global named 'd3'. I'm calling rollup from a simple npm script. The good news is that almost everything works in the output file, except for one thing: d3.event
in browser is always null. No, it's not an issue with events being hijacked on the page. When I swap in the standard full d3 4.0 library into the script tag everything works fine. It's definitely a build issue.
The d3 docs warn that bundling event
is tricky:
If you use Babel, Webpack, or another ES6-to-ES5 bundler, be aware that the value of d3.event changes during an event! An import of d3.event must be a live binding, so you may need to configure the bundler to import from D3’s ES6 modules rather than from the generated UMD bundle; not all bundlers observe jsnext:main. Also beware of conflicts with the window.event global.
It appears that setting nodeResolve({ jsnext: true })
isn't sufficing. How do I get a live binding in the bundle? Any guidance very appreciated.
You’re exporting an object, defined using ES2015 shorthand object literal syntax, as the default export. Here is the long form equivalent of what you’ve written:
export default {
range: range,
select: select,
selectAll: selectAll,
event: event,
transition: transition
}
Your object thus captures the value of event
on load, which is null; it is not a live binding, and won’t reflect the current event.
One fix would be to define the event
property using a getter:
export default {
range,
select,
selectAll,
get event() { return event; },
transition
}
Better would be to use named exports instead of a default export, and then Rollup will generate a live binding automatically:
export {
range,
select,
selectAll,
event,
transition
}
This is not only shorter, but now you don’t depend on the browser supporting the ES2015 shorthand object literal syntax.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With