'Can I use ES Modules library from CDN?
I want to use this library via CDN.
https://www.jsdelivr.com/package/npm/lit-element
My js code is here.
import { LitElement, html } from "https://cdn.jsdelivr.net/npm/[email protected]/lit-element.js";
class MyElement extends LitElement {
render(){
return html`ABCD`
}
}
customElements.define("my-element", MyElement)
I get following error.
Uncaught TypeError: Failed to resolve module specifier "lit-html". Relative references must start with either "/", "./", or "../".
Do I have to build using npm ?
Update
Following code works.
import { LitElement, html } from "https://unpkg.com/lit-element/lit-element.js?module"
class MyElement extends LitElement {
render(){
return html`ABCD`
}
}
customElements.define("my-element", MyElement)
Solution 1:[1]
Inside LitHtml and LitElement modules use bare module specifiers internally to import dependencies, and these aren't supported by JS modules yet. LitElement
has import { TemplateResult } from 'lit-html'
, but JS needs that 'lit-html'
replaced with whatever path to the actual file (not the abstract name of the package).
If you use the npm packages (which cdn.jsdelivr.net
is serving up here) you have to use a build step (WebPack, Rollup, etc) to resolve all those import
statements to either the file paths JS supports or inline all the files together.
The former is what unpkg.com ... ?module
does, it replaces the bare reference to lit-html
with the absolute https://unpkg.com/lit-html@^1.1.1/lit-html.js?module
.
Solution 2:[2]
The accepted answer is great; the core issue is your CDN file(s) use a "module specifier" that is the "bare" specifier (i.e. not using "/" or "./" or "../") . I fixed my issue with an importmap
, mapping my "bare" module specifier, to a full URL/baseURL specifier, i.e.
<script type="importmap">
{ "imports": { 'bare-specificer': 'https://full-url-specifier' } }
</script>
DETAIL ON CURRENT APPROACH: importmap
I was using jsm three.js
modules like ColladaLoader
, but I got this error:
Uncaught TypeError: Failed to resolve module specifier "three". Relative references must start with either "/", "./", or "../"
This happens because I import this ColladLoader.js
file, which imports many things from 'three'
(a "bare module specifier"):
import {
AmbientLight,
// ...etc....
sRGBEncoding
} from 'three';
//--------^ this is the "bare" module specifier problem
For the fix I referenced the collada loader example from three.js, which adds an importmap
to its html. I think importmap
is still a draft feature but it works well to map a "bare module specifier" to a full URL /baseURL
-- just what we need! (more here and here):
<script type="importmap">
{
"imports": {
"three": "../build/three.module.js"
}
}
</script>
<script type="module">
//...
</script>
In my case I am using the three.js
file located here:
https://cdnjs.cloudflare.com/ajax/libs/three.js/r123/three.module.js
Therefore my importmap
looks like this:
<script type="importmap">
{
"imports": {
"three": "https://cdnjs.cloudflare.com/ajax/libs/three.js/r123/three.module.js"
}
}
</script>
<script type="module">
//...
</script>
I expect an importmap
can work for you even if you have a "bare" module specifier from somewhere other than three.js
; but the importmap
approach may only work in certain browsers (i.e. caniuse suggests Edge 89+, Chrome 89+, and Opera 76+ support type="importmap"
as of 5/4/2022)
DETAIL ON ALTERNATIVE APPROACH: skypack
THE BELOW ANSWER DEPENDS ON skypack
hosting up-to-date modules; i.e. the latest ColladaLoader
should use BufferGeometry
instead of Geometry
which was deprecated with the change in r125, but the latest ColladaLoader
was not available on skypack AFAIK
I'm providing this answer to suggest skypack
as an alternative to your CDN, which works especially in the context of three.js
, (apparently even unpkg
might not work; read on)
The solution is discussed in this github issue, which references this migration guide
NPM: ES6 modules in examples/jsm now import using the bare specifier three. This change breaks working with modules in cdns such as https://www.jsdelivr.com/ and https://unpkg.com/. Please use https://www.skypack.dev/ instead.
So in my case I replaced this line:
import { ColladaLoader } from 'https://cdn.jsdelivr.net/gh/mrdoob/three.js/examples/jsm/loaders/ColladaLoader.js';
with this line:
import ColladaLoader from 'https://cdn.skypack.dev/three-collada-loader';
This fixed the error re "Failed to resolve module specifier". But I did face a different issue, but that's three.js
specific; i.e. using the deprecated Geometry
constructor, because I guess the skypack.dev/three-collada-loader
is not the latest code...
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Keith |
Solution 2 |