New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Build as UMD module and test in AMD #26
Conversation
Added in `--standalone` option to Browserify build. Updated the standalone file to return the selection module. Added a test showing functionality with AMD.
OK, it appears that this can work. Some nuances:
The goal of breaking up D3 into separate modules is that users can conveniently pick which parts of D3 they need. For example, say they want to add d3-selection-multi for multi-value map support. In Vanilla mode, that would mean something like this: <script src="d3-selection.js"></script>
<script src="d3-selection-multi.js"></script>
<script>
d3.select("body").attrs({hello: "world"});
</script> In RequireJS mode, like this, perhaps? <script>
require(["d3-selection"], function(d3) {
require(["d3-selection-multi"], function() {
d3.select("body").attrs({hello: "world"});
});
});
</script> The nested require is unfortunate, but I don’t know how to declare that d3-selection-multi depends on a module named “d3-selection” (without also defining where that named module lives, since I want people to be able to load the d3-selection module from anywhere). See the standalone.js in d3-selection-multi for how it works. |
Yes those nuances make sense for how anyone would expect to use d3, but make it a little trickier. Browserify can create standalone modules in a namespace like You could create every single method of d3 as a standalone module... but no. I think this would need a custom browserify transform to do what you want in a clean way, unless there is already a transform or plugin that would do it. I have a feeling that what you need is somewhere in https://github.com/thlorenz/browserify-shim but I'm getting out of my depth... |
One way (the only way?) of doing this is a custom browserify plugin. This branch creates a standalone module that attaches all methods to an existing global This is a bit of a hack. The plugin inserts this code into the UMD created by browserify (with a RegExp replace): g.d3 = g.d3 || {};
var moduleExports = f();
for (var key in moduleExports) {
if (moduleExports.hasOwnProperty(key)) {
g.d3[key] = moduleExports[key];
}
} A neater way to do this would require modifying ForbesLindesay/umd to allow standalone modules to optionally extend globals. Not sure if this is the best way of doing things. Buying into the npm / commonjs ecosystem does have advantages for those who are writing browser code with npm and browserify. Can write code like this to pick components of d3 as needed: var d3 = {
selection = require('d3-selection'),
mouse = require('d3-selection/lib/d3/event').mouse,
json = require('d3-xhr/lib/d3/json)
} The more modular the files, the less overhead in the browserified code, approaching what Smash creates. |
Proposed solution in #30. Seems simple and achieves what we need? (You can still use Browserify to make custom builds; you’ll be using the files in lib/, though, not standalone.) |
Superseded by #30. |
Added in
--standalone
option to Browserify build. Updated thestandalone file to return the selection module. Added a test showing
functionality with AMD.