今どきのnpmパッケージはUNPKGPika CDNを使えば、ES Modulesとして直接import文読み込めることがあります。

たとえばPreactなら、次のようにUNPKG経由で直接モジュールをインポートできます。

<script type="module">
  import { h, Component, render } from 'https://unpkg.com/preact?module';

  // Create your app
  const app = h('h1', null, 'Hello World!');

  render(app, document.body);
</script>

これは、ECMAScript Modulesに対応しているブラウザでしか動きませんが、モダンなブラウザのみ対象のサイトならbundlerなどのツールを使わずにライブラリを気軽に利用できます。(最適化する場合はbundlerを使った方がよさそうですが)

ECMAScriptのimport文自体については次を参照してください。

しかし、このUNPKGPika CDNからすべてのライブラリが直接Importできるわけではありません。 これを行うにはライブラリ側がpackage.jsonmoduleフィールに対応している必要があります。

そのため、ES Modulesに対応してないライブラリ(UMD形式のみ配布するライブラリなど)は、<script>タグで読み込んでグローバルに追加されたメソッドを使う必要があります。

また、UIライブラリに含まれるCSSファイルなどもUNPKGなどから取得はできますが、 ES ModulesではCSSファイルは読み込めないためlinkタグなどを使って読み込む必要があります。

このようにライブラリごとに読み込み方法が異なるため、ES Modulesに対応していないJSやCSSの読み込みをラップするdynamic-import-assetsというパッケージを書きました。

dynamic-import-assets

dynamic-import-assetsは、Modulesに対応していないJavaScriptやCSSを読み込むローダーライブラリです。

たとえば、@evillt/toastというToast UIを提供するライブラリは、<script>タグでJavaScriptを読み込み、<link rel=stylesheet>でCSSを読み込んでから扱います。

<link rel="stylesheet" href="https://unpkg.com/@evillt/toast/dist/toast.min.css" />
<script src="https://unpkg.com/@evillt/toast"></script>
<script>
  toast.createToast('Hello world')
</script>

これをUNPKGdynamic-import-assetsを使えば次のように書けます。

(async function main(){
    const { dynamicImportJS, dynamicImportCSS } = await import("https://unpkg.com/dynamic-import-assets?module");
    await Promise.all([
        // inject <link rel="stylesheet">
        dynamicImportCSS("https://unpkg.com/@evillt/toast/dist/toast.min.css"),
        // inject <script>
        dynamicImportJS("https://unpkg.com/@evillt/toast")
    ]);
    // use toast after loaded 
    toast.createToast("Hello world");
})();

既存方法で<script>タグや<link>タグをHTMLに書いてしまうと、ライブラリが必要ない場合も読み込んでしまいます。

dynamic-import-assetsではJavaScriptやCSSのロードをJavaScriptから行うため、 必要なタイミングで動的にライブラリを取得できます。

たとえば、次のように?show_toastというクエリがURLに付いてるときのみToast表示をしたい場合は次のように書けます。

(async function main(){
    // ?show_toast
    const showToast = (new URL(location.href)).searchParams.has("show_toast")
    if (!showToast) {
        return;
    }
    const { dynamicImportJS, dynamicImportCSS } = await import("https://unpkg.com/dynamic-import-assets@^1.0.0?module");
    await Promise.all([
        dynamicImportCSS("https://unpkg.com/@evillt/[email protected]/dist/toast.min.css"),
        dynamicImportJS("https://unpkg.com/@evillt/[email protected]")
    ]);
    toast.createToast("Hello world");
})();

おわりに

モダンなブラウザのみが対象なら、ES Modules(import文やDynamic Imports)を使ってUNPKGPika CDNを使って、 npmに公開されているライブラリを直接読み込めることがあります。

<script>タグで読み込む方法と違ってグローバルに読み込む必要もなくなるため、ちょっとしたサイトでちょっとしたライブラリを使う場合には便利です。

ただし、ES Modules形式で配布していないライブラリやCSSは<script><link>タグまたはDOM APIを使って読み込む必要があります。 これらのライブラリもDynamic Importsと同じように書き方で読み込めるものが欲しかったのでdynamic-import-assetsを作りました。

逆にライブラリ作者側でES Modules形式も配布したい場合は、次のようなビルドツールを使うのが良いかもしれません。

この辺でまだこなれたツールがないのも、ES Modules形式で配布しているライブラリが少ない原因かもしれません。