Chrome 89 から使えるようになった importmap を使ってみた
- カテゴリ:
- JavaScript
- Chrome
- コメント数:
- Comments: 2
◆ import 時に importmap で指定したパスから import できる
◆ 絶対パス・相対パス以外に Node.js で使われるパッケージ名を使うこともできる
◆ node_modules 内ではパッケージ名で import されるので rollup などが必要だったのがいらなくなる
◆ 絶対パス・相対パス以外に Node.js で使われるパッケージ名を使うこともできる
◆ node_modules 内ではパッケージ名で import されるので rollup などが必要だったのがいらなくなる
Chrome 89 がリリースされたので気になっていた importmap を使ってみました
Node.js のようにパッケージ名だけ書くのはエラーです
例えば lit-html をロードする場合 こうなります
HTML と同じフォルダに node_modules を配置していれば相対パスでこうなります
1 ファイルならともかく複数のモジュールに分けてそれぞれが lit-html をロードする場合 絶対パスを全部に書くのは面倒です
相対パスでもフォルダ階層が変わればパスが変わるので不便です
importmap を使えば Node.js と同じようにパッケージ名を書くだけにできます
script タグに type="importmap" を指定して JSON を書きます
中身は imports キーに import のマッピングをオブジェクトで指定します
ドキュメントによると URL は配列にして複数書くこともできるようです
「@std/kv-storage」がなければ polyfill をロードする例のようです
それ以外にも CDN を複数指定しておいて 1 つめの CDN が落ちていたら 2 つめからダウンロードということにも使えそうです
importmap を使って lit-html をロードしてみます
モジュール内では from に "lit-html" のみの指定で動いています
これまで lit-element を ES Modules で使おうとすると lit-html のロードで問題がありました
lit-element の内部で lit-html をロードしようとしますが そこではパッケージ名で "lit-html" が指定されています
ここで絶対パス・相対パスが使われていないのでエラーとなります
この問題の対策として全体を webpack したり node_modules 内のパッケージ部分のみを rollup や snowpack したりという対処が必要でした
importmap を使えばこれにも対処できて バンドラーが不要になります
importmap では import 時に指定される名前全体を書く必要があるようで
のような設定をしておけば "lit-html/lit-html.js" の import は "./node_modules/lit-html/lit-html.js" を import してくれる ということにはできませんでした
外部からパッケージ名を通して import されるモジュールを全部書かないといけないのは面倒ですが これまでに比べると便利になりました
https://github.com/WICG/import-maps
マッピングに指定する名前の最後を "/" にすると パッケージ内の全ファイルを importmap に書かなくて良いようです
上の例は ⇩のように書いても動きました
また importmap の JSON のトップレベルに imports 以外に scopes も設定できて 特定のスコープ内でのみ有効なマッピングを設定できるようです
importmap
これまで ES Modules の import で指定するモジュールの場所は相対パスか絶対パスを書く必要がありましたNode.js のようにパッケージ名だけ書くのはエラーです
例えば lit-html をロードする場合 こうなります
import { html, render } from "https://unpkg.com/lit-html?module"
HTML と同じフォルダに node_modules を配置していれば相対パスでこうなります
import { html, render } from "./node_modules/lit-html/lit-html.js"
1 ファイルならともかく複数のモジュールに分けてそれぞれが lit-html をロードする場合 絶対パスを全部に書くのは面倒です
相対パスでもフォルダ階層が変わればパスが変わるので不便です
importmap を使えば Node.js と同じようにパッケージ名を書くだけにできます
script タグに type="importmap" を指定して JSON を書きます
中身は imports キーに import のマッピングをオブジェクトで指定します
{
"imports": {
"lit-html": "https://unpkg.com/lit-html?module"
}
}
ドキュメントによると URL は配列にして複数書くこともできるようです
「@std/kv-storage」がなければ polyfill をロードする例のようです
それ以外にも CDN を複数指定しておいて 1 つめの CDN が落ちていたら 2 つめからダウンロードということにも使えそうです
importmap を使って lit-html をロードしてみます
<!doctype html>
<script type="importmap">
{
"imports": {
"lit-html": "https://unpkg.com/lit-html?module"
}
}
</script>
<script type="module">
import { html, render } from "lit-html"
render(html`<h1>a</h1>`, document.getElementById("root"))
</script>
<div id="root"></div>
モジュール内では from に "lit-html" のみの指定で動いています
node_modules
単に絶対パス・相対パスを書くのが楽になるだけでなく node_modules のモジュールをロードする場合にも助かりますこれまで lit-element を ES Modules で使おうとすると lit-html のロードで問題がありました
lit-element の内部で lit-html をロードしようとしますが そこではパッケージ名で "lit-html" が指定されています
ここで絶対パス・相対パスが使われていないのでエラーとなります
この問題の対策として全体を webpack したり node_modules 内のパッケージ部分のみを rollup や snowpack したりという対処が必要でした
importmap を使えばこれにも対処できて バンドラーが不要になります
<!doctype html>
<script type="importmap">
{
"imports": {
"lit-html/lit-html.js": "./node_modules/lit-html/lit-html.js",
"lit-html/lib/shady-render.js": "./node_modules/lit-html/lib/shady-render.js",
"lit-element": "./node_modules/lit-element/lit-element.js"
}
}
</script>
<script type="module">
import { html, LitElement } from "lit-element"
customElements.define("elem-1", class extends LitElement {
render() {
return html`<h1>a</h1>`
}
})
</script>
<elem-1></elem-1>
importmap では import 時に指定される名前全体を書く必要があるようで
{
"lit-html": "./node_modules/lit-html"
}
のような設定をしておけば "lit-html/lit-html.js" の import は "./node_modules/lit-html/lit-html.js" を import してくれる ということにはできませんでした
外部からパッケージ名を通して import されるモジュールを全部書かないといけないのは面倒ですが これまでに比べると便利になりました
追記
Github にもっと詳しいドキュメントがありましたhttps://github.com/WICG/import-maps
マッピングに指定する名前の最後を "/" にすると パッケージ内の全ファイルを importmap に書かなくて良いようです
上の例は ⇩のように書いても動きました
{
"imports": {
"lit-html/": "./node_modules/lit-html/",
"lit-element": "./node_modules/lit-element/lit-element.js"
}
}
また importmap の JSON のトップレベルに imports 以外に scopes も設定できて 特定のスコープ内でのみ有効なマッピングを設定できるようです