Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
485 views
in Technique[技术] by (71.8m points)

javascript - importing d3.event into a custom build using rollup

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...