hello friends! i’m experimenting with the future, today!
i’m really excited since all the cool browsers support proper es-modules, so i’ve been upgrading my typescript libraries to emit es-modules and umd-modules, and in new projects, i’ve been experimenting with having no build-step at all. it feels very liberating!
so given the following code to load babylon via unpkg (which seems to be an awesome hipster replacement for npm, from the future!) (here’s this example on codepen)
import * as babylon from "https://unpkg.com/@email@example.com/index.js" document.body.textContent = "done!"
i’ve found two potential issues:
module specifiers are lacking the required extensions
when we look at @babylonjs/core/index.js (
https://unpkg.com/@firstname.lastname@example.org/index.js) we can see that the emitted module specifiers do not have extensions
omitting the extensions is not valid, however in our example case, unpkg goes one extra step to counteract the problem: it will serve the
.jsfile for any file requested without an extension (eg, “index” becomes “index.js” thanks to the unpkg server, but this is non-standard behavior that should not be relied on) (other npm-cdn’s, like jsdelivr, don’t seem to offer this helpful hack)
the lack of extensions causes loading babylon via jsdelivr to fail (which doesn’t have the
?modulehack feature) —
import * as babylon from "https://cdn.jsdelivr.net/npm/@email@example.com/index.js"
note that there are ongoing debates (
https://github.com/nodejs/modules/issues/293) on whether the future of es modules on the web should be expressed as
at first in my own projects, i found this requirement confusing, because typescript doesn’t have a compiler option to emit a particular extension in the module specifiers — however as a solution, i found that typescript seems to be designed, for this purpose, to ignore file extensions in your typescript sourcecode – such that you can tweak all of your module references (in your ts source) to, for example,
export * from "./abstractScene.js";(adding the
.js) – and typescript is totally relaxed about it, and will emit the desired extension, and so typescript is smart enough to know that
abstractScene.jsis the same as
user workaround: rely on unpkg’s rewriting hack for now
inevitable babylon solution: add
.jsextensions to all module references in babylon’s typescript sourcecode (or otherwise
.mjs, if that one floats your boat)
"bare specifier" module references
the following error is thrown:
Uncaught TypeError: Failed to resolve module specifier "tslib". Relative references must start with either "/", "./", or "../".
there are some bare specifiers in babylon referencing
tslib, at least for the decorator function, it looks to me
bare specifiers are reserved (
https://html.spec.whatwg.org/multipage/webappapis.html#resolve-a-module-specifier) for builtin modules, however in the future, we’ll be able to rewrite them via import-maps
how to fix it:
(future solution) we’ll use import-maps (
https://github.com/WICG/import-maps) to remap the bare-specifiers
(workaround-a) we can use es-module-shims (
https://github.com/guybedford/es-module-shims) to shim the import maps see the codepen demo (
(workaround-b) unpkg has a
?modulefeature which rewrites bare specifiers (see my reply post for more details)
thanks for reading, and of course it goes without saying, i’m no authority on how es modules work — we’re all learning and developing these new ideas together, so if i seem misguided or there’s a different way to think about or avoid these problems, i’d love to discuss it, so please speak up!
if you’d like me to post a github issue, just let me know
cheers everybody, keep making web games
edit: hmm, this form limits me to two real links, sorry but you’ll have to copy-paste if you want to follow them