Closed brainwipe closed 5 years ago
You’re trying to import from the UMD bundle, but you can only ES import from an ES module.
I don’t currently provide pre-bundled ES modules. Furthermore, the current D3 source uses bare import specifiers to allow the source to be split into modules with dependencies tracked in package.json files, so you can only import the D3 source directly if you happen to need the subset that does not have any (package) dependencies.
If the module you want doesn’t have any dependencies, such as d3-array, you can import the source directly. For example, you can import index.js from d3-array:
import * as d3Array from "./d3-array/src/index.js";
If the module does have dependencies, then you need something to resolve the bare import specifiers, such as Rollup or Unpkg. Eventually, browsers will hopefully support import maps to give you control over bare specifier resolution. For example, here’s how to import D3 using ES modules from unpkg:
import * as d3 from "https://unpkg.com/d3@5?module";
But again, D3 does not provide a pre-bundled ES module, so if you load D3 directly from its source (with something to resolve bare specifiers), you’ll make 500+ requests for non-minified source, which typically isn’t a good idea for performance reasons.
There doesn’t seem to be a good way to support ES module loading with package dependencies at the moment. My preference would be for package distributors such as Unpkg to provide this service, e.g. https://github.com/unpkg/unpkg.com/issues/152, and allow library maintainers to worry only about distributing source and not supporting myriad inconsistent environments.
Thank you, Mike for both an excellent library and taking the time to explain the situation in your well considered reply.
For those arriving on this thread, the solution I used was to use the d3 modules as if they were vanilla, just like in the d3-force instructions:
<script src="https://d3js.org/d3-dispatch.v1.min.js"></script>
<script src="https://d3js.org/d3-quadtree.v1.min.js"></script>
<script src="https://d3js.org/d3-timer.v1.min.js"></script>
<script src="https://d3js.org/d3-force.v2.min.js"></script>
You can then use d3 from within your class without an import:
export default class {
constructor() {
var simulation = d3.forceSimulation() //etc
}
}
As Mike rightly points out, you have to ensure you get all the dependencies (in this case dispatch, quadtree and timer) but you'll find that if you miss one, the browser will tell you that it can't find a function, such as "quadtree", in that case, just find the d3 package and add it.
This will attach d3 to the global window
scope. Unless you're running lots of versions of d3 or something with a namespace clash (unlikely) then this solution works fine.
The solution will mostly be used offline, so the number of HTTP requests isn't an issue and I'm not using other modules except d3 as my code is mostly algorithmic in nature.
It should be obvious across all d3 sites that when creating a vanilla site, you can't use vanilla
import
without an AMD, packaging or loading. For example, in Chrome 71:index.html
mymodule.js
Chrome reports that d3 does not have any exports. This problem was also reported by another user on Stack Overflow.
Is there any plan to support vanilla js module loading?