How to set up rollup.js with a d3 plugin?

我的未来我决定 提交于 2021-02-11 13:38:25

问题


I currently write a d3 plugin. However, I want to call this plugin as property of the global d3 as in the original example: d3.foo() But when I do this, my configurations for rollup lead to a clash of the d3 references.

Here is one minimal example (with just one file) to illustrate: I downloaded the original example of the d3 plugin and slightly changed the source file foo.js:

//.src/foo.js
import * as d3 from "d3";

export default function() {
  return d3.select("body").append("div").text(42); 
};

So here is my plugin. It uses d3 functions (d3.select()) therefor d3 is imported at the top.

My index.js looks like this:

export {default as foo} from "./src/foo";

So I export the function foo().

My rollup.config.js looks like this:

//rollup.config.js
import babel from "rollup-plugin-babel";

var globals = { 
  "d3": "d3",
};

export default {
  entry: "index.js",
  dest: "build/d3-foo.js",
  format: "umd",
  moduleName: "d3",
  external: Object.keys(globals),
  globals: globals,
  plugins: [
    babel({
      exclude: "node_modules/**"})
  ]
};

I have set moduleName to "d3" since I want to call my plugin as d3.foo(). I also set the globals and external to "d3" since I don't want the d3 modules to be bundled by rollup.

To call my d3 plugin I use the following html code:

<!DOCTYPE html>
  <head>
    <meta charset="utf-8">
    <script src="https://d3js.org/d3.v5.js"></script>
    <script src="./build/d3-foo.js"></script>
  </head>
  <body>
    <script>
       d3.foo();
    </script>
  </body>
</html>  

But this does not work since the d3 namespace is refering to the d3 library which does not contain a function called d3.foo().

The generated bundle looks like this:

// build/d3-foo.js
(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3')) :
  typeof define === 'function' && define.amd ? define(['exports', 'd3'], factory) :
  (factory((global.d3 = {}),global.d3));
}(this, (function (exports,d3) { 'use strict';

  function foo () {
    return d3.select("body").append("div").text(42);
  }

  exports.foo = foo;

  Object.defineProperty(exports, '__esModule', { value: true });

})));

If instead I call the moduleName in rollup.config.js any other name (e.g. d4) I can call the plugin with d4.foo() and it works. How do need to adjust the rollup config file to be able name my plugin d3.foo as suggested by mike bostock in his blog?

Any help would be greatly appreciated!


回答1:


I found a solution how the desired final bundle should look like, thanks to Mike Bostock.

The rollup.config.js can be specified as follows:

// rollup.config.js
import babel from "rollup-plugin-babel";
import * as meta from "./package.json";

export default {
  input: "index.js",
  external: ["d3"],
  output: {
    file: `build/${meta.name}.js`,
    name: "d3",
    format: "umd",
    indent: false,
    extend: true,
    // banner: `// ${meta.homepage} v${meta.version} Copyright ${(new Date).getFullYear()} ${meta.author}`,
    globals: {d3: "d3"},
    plugins: [
      babel({
        exclude: "node_modules/**"})
    ]
  },
};

...resulting in the following bundle:

// build/d3-foo.js
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3')) :
typeof define === 'function' && define.amd ? define(['exports', 'd3'], factory) :
(factory((global.d3 = global.d3 || {}),global.d3));
}(this, (function (exports,d3) { 'use strict';

function foo() {
  return d3.select("body").append("div").text(42); 
}

exports.foo = foo;

Object.defineProperty(exports, '__esModule', { value: true });

})));


来源:https://stackoverflow.com/questions/60460975/how-to-set-up-rollup-js-with-a-d3-plugin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!