billboard.js
billboard.js copied to clipboard
Billboard fails to load as an ES6 module
Description
I'm trying to use billboard as a dependency in a dynamically loaded module, which tries to load billboard with:
import './billboard.js';
But this fails with the error TypeError: Cannot read properties of undefined (reading 'd3')
. Debugging tells me that the issue is due to this
being undefined in a module. The this
usage at billboard.js 3.3.3 line 16 seems to be meant to be the window object.
As the module doing the import is dynamically loaded, I cannot add the billboard script tag to the html.
I've also tried the billboard.pkgd.js
script, resulting in TypeError: Cannot set properties of undefined (setting 'bb')
. Debugging shows a similar setup as in the billboard.js
script, trying to use this
as the window
object.
Is there a way to use billboard as an import in this way? Or can you modify the script to use the window
object?
Steps to check or reproduce
<script type="module" src="some-module.js"></script>
// some-module.js
import './d3.min.js';
import './billboard.js'; // fails
// do something with billboard
Working solution:
--- a/billboard
+++ b/billboard_1
@@ -16,7 +16,7 @@
var a = typeof exports === 'object' ? factory(require("d3-axis"), require("d3-brush"), require("d3-drag"), require("d3-dsv"), require("d3-ease"), require("d3-interpolate"), require("d3-scale"), require("d3-selection"), require("d3-shape"), require("d3-time-format"), require("d3-transition"), require("d3-zoom")) : factory(root["d3"], root["d3"], root["d3"], root["d3"], root["d3"], root["d3"], root["d3"], root["d3"], root["d3"], root["d3"], root["d3"], root["d3"]);
for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
}
-})(this, function(__WEBPACK_EXTERNAL_MODULE__10__, __WEBPACK_EXTERNAL_MODULE__3__, __WEBPACK_EXTERNAL_MODULE__7__, __WEBPACK_EXTERNAL_MODULE__5__, __WEBPACK_EXTERNAL_MODULE__11__, __WEBPACK_EXTERNAL_MODULE__12__, __WEBPACK_EXTERNAL_MODULE__6__, __WEBPACK_EXTERNAL_MODULE__2__, __WEBPACK_EXTERNAL_MODULE__9__, __WEBPACK_EXTERNAL_MODULE__4__, __WEBPACK_EXTERNAL_MODULE__8__, __WEBPACK_EXTERNAL_MODULE__13__) {
\ No newline at end of file
+})(this || window, function(__WEBPACK_EXTERNAL_MODULE__10__, __WEBPACK_EXTERNAL_MODULE__3__, __WEBPACK_EXTERNAL_MODULE__7__, __WEBPACK_EXTERNAL_MODULE__5__, __WEBPACK_EXTERNAL_MODULE__11__, __WEBPACK_EXTERNAL_MODULE__12__, __WEBPACK_EXTERNAL_MODULE__6__, __WEBPACK_EXTERNAL_MODULE__2__, __WEBPACK_EXTERNAL_MODULE__9__, __WEBPACK_EXTERNAL_MODULE__4__, __WEBPACK_EXTERNAL_MODULE__8__, __WEBPACK_EXTERNAL_MODULE__13__) {
\ No newline at end of file
return /******/ (function() { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ([
Hi @qsiebers, from the billboard.js npm package distribution, it provides different modules types to be consumed: UMD or ESM. In general circumstances, based on your dev environment, it will pick up the right module (module resolution) types.
- https://github.com/naver/billboard.js/blob/master/package.json#L10
But if you're loading it directly(not by package resolution) as ESM, try using the distribution from dist-esm
folder.
- https://unpkg.com/browse/[email protected]/
The dist
folder contains UMD type and dist-esm
contains native ESM type.
But if you're loading it directly(not by package resolution) as ESM, try using the distribution from dist-esm folder.
Ah, I saw that there were different dists, but I've seem to have missed the dist-esm folder.
Unfortunately this version also does not work as-is in the browser. The imports at line 10-21 are not valid in the browser:
Uncaught TypeError: Failed to resolve module specifier "d3-time-format". Relative references must start with either "/", "./", or "../".
For the browser they have to be relative, and have to actually resolve to a file so an extension is also required. You can see this error in this pen:
https://codepen.io/qsiebers/pen/oNpeXvB?editors=1111
... based on your dev environment ...
This is where my difficulty lies. I'm trying to use billboard as an import directly from the dist into the browser via webjars. There is no npm/bower/yarn/... nor webpack to resolve and bundle things for me, as it would require my entire framework front-end to be overhauled. Eventually that might happen, but not today.
The ESM distribution's dependencies imports are pointed as "module-name". When you check the billboard.js' ESM dist file, all the necessary dependencies imports are defined at the top as:
import { timeParse, utcParse, timeFormat, utcFormat } from 'd3-time-format';
import { pointer, select, namespaces, selectAll } from 'd3-selection';
...
So, to execute it needs load those imports first. As you pointed, to be imported directly to the browser (w/o transpilation), the "module-name" location should be relative or some origin where browser could identify.
If you aren't aware on browser compatibility, you can use import maps to fix that.
<!-- specify importmaps to mapping dependencies modules and its location --->
<script type="importmap">
{
"imports": {
"d3-time-format": "https://cdn.skypack.dev/d3-time-format",
"d3-selection": "https://cdn.skypack.dev/d3-selection",
"d3-brush": "https://cdn.skypack.dev/d3-brush",
"d3-dsv": "https://cdn.skypack.dev/d3-dsv",
"d3-drag": "https://cdn.skypack.dev/d3-drag",
"d3-scale": "https://cdn.skypack.dev/d3-scale",
"d3-transition": "https://cdn.skypack.dev/d3-transition",
"d3-axis": "https://cdn.skypack.dev/d3-axis",
"d3-ease": "https://cdn.skypack.dev/d3-ease",
"d3-interpolate": "https://cdn.skypack.dev/d3-interpolate",
"d3-shape": "https://cdn.skypack.dev/d3-shape",
"d3-zoom": "https://cdn.skypack.dev/d3-zoom"
}
}
</script>
<script type="module">
import bb, {area, line} from "https://unpkg.com/billboard.js/dist-esm/billboard.js";
bb.generate( ... );
</script>
And here's working demo:
- https://codepen.io/netil/pen/NWXvJrW
If you aren't aware on browser compatibility, you can use import maps to fix that.
I was not yet aware of import-maps, thanks for the pointer! I'll have to experiment a bit and see how this matches our browser compatibility requirements.
But if you're loading it directly(not by package resolution) as ESM, try using the distribution from dist-esm folder.
This might be an interesting point to add to the readme.