Chapter 16

npmパッケージを使用する

uki00a
uki00a
2023.02.01に更新

Denoを対象に書かれたパッケージは、基本的にdeno.land/xnest.landなどのレジストリで公開されることが多いです。

しかし、これらのレジストリに目当てのモジュールが見つからない場合もあるかと思います。

そのような場合は、npmパッケージの使用を検討してみるとよいかもしれません。

この章では、Denoからnpmパッケージを使用する方法について2つ紹介します。

npm:URLを使用する

Denoでパッケージをimportする際に、npm:<パッケージ名>@<バージョン>という形式のURLを指定すると、対象のパッケージをnpmレジストリから読み込んでくれます。

main.mjs
import chalk from "npm:chalk@5.0.1";
console.info(chalk.green("Hello, world!"));

実行する際は通常通り、deno runコマンドを利用できます。

$ deno run --allow-env --allow-read main.mjs

通常のサードパーティモジュールと同様に、初回実行時のみnpmレジストリからパッケージがダウンロードされ、以降はローカルにキャッシュされたパッケージが利用されます。

deno runの引数にnpm:形式のURLを指定することも可能で、Node.jsにおけるnpxコマンドのようにnpmパッケージで提供されるコマンドを直接実行することもできます。

$ deno run --unstable --allow-env --allow-read --allow-write npm:make-dir-cli@3.0.0 src/components

npm:URLでパッケージを読み込んだ際に、Node.jsの組み込みパッケージへの読み込みはdeno_std/nodeの読み込みに置き換えられます。

そのため、Node.jsのAPIに依存したパッケージもある程度動作させることができます。

npmパッケージを配布するCDNを利用する

Denoからnpmパッケージを利用する際の手段として、CDNから対象パッケージを直接importする方法があります。

esm.shSkypackなどのCDNはX-TypeScript-Typesヘッダ[1]をサポートするため、CDNから直接npmパッケージを読み込みたいときは、これらの利用を検討するとよいかと思います。

例えば、以下はesm.shからfast-xml-parserパッケージを読み込む例です。

import { XMLParser } from "https://esm.sh/fast-xml-parser@4.0.9";

const xmlDocument = await Deno.readTextFile("./test.xml");
const parser = new XMLParser();
const obj = parser.parse(xmlDocument);
(補足) esm.shについて

esm.shは、クエリパラメータによって柔軟に挙動を制御することができます。

Denoからnpmパッケージを利用する上で便利な様々なパラメータが提供されており、FreshAleph.jsなどのフレームワークでも活用されています。

いくつか例を挙げると、次のような機能があります。

  • ?no-checkパラメータを指定すると、X-TypeScript-Typesヘッダの付与が無効化されます。
    https://esm.sh/fast-xml-parser@4.0.9?no-check
    
  • "peerDependencies"を利用したパッケージを使用したいときは、?externalパラメータとImport mapsを併用すると便利です。
    import_map.json
     {
       "imports": {
         "preact": "https://esm.sh/preact@10.10.0",
         "preact-render-to-string": "https://esm.sh/preact-render-to-string@5.2.0?external=preact",
       }
     }
    
  • ?aliasパラメータは、あるパッケージを別のパッケージの読み込みへ置換してくれるため、preact/compatなどのパッケージを活用したいときなどに便利です。
  • Node.jsのAPIに依存したパッケージを利用するために、組み込みパッケージをdeno_std/nodeへの読み込みに置換してくれます。

esm.shにはこの他にも様々な機能があります。

より詳しくは公式ドキュメントを参照ください。

(補足) X-TypeScript-TypesヘッダをサポートしないCDNを利用する必要が出てきたときは?

X-TypeScript-TypesヘッダをサポートしないCDNからJavaScriptパッケージをimportした場合、Denoはそのパッケージの型定義を判断することができません。

この問題を解消するため、Denoには@deno-typesという機能が提供されています。

// @deno-types="https://esm.sh/testdouble@3.16.1/index.d.ts"
export * as td from "https://esm.sh/testdouble@3.16.1/dist/testdouble.js";

このように、あるパッケージに対応する型定義ファイルの場所をDenoに知らせることができます。

どの方法を使うべき?

基本的には、npm:URLを使うのがよいかと思います。

Deno本体に組み込まれた機能であり、将来に渡って改善やメンテナンスが継続される可能性が高いと考えられるためです。

ただし、FreshAleph.jsなどのようにesm.shの使用を想定したフレームワークも存在するため、esm.shの使い方についても把握しておくと便利な場合もあるかと思います。

いずれの方法を利用するにせよ、Import mapsなどで依存関係を管理しておくことで、いずれかの方法に素早く移行する余地が生まれるため、活用しておくとよいでしょう。

ポイント

  • npm:URLを利用することで、npmレジストリから直接パッケージをimportすることができます。
  • CDNからnpmパッケージを読み込む場合は、esm.shなどのX-TypeScript-TypesヘッダをサポートするCDNを利用すると便利です。
脚注
  1. X-TypeScript-TypesヘッダはDenoがJavaScriptで書かれたモジュールに対して型を適用するための独自機能です。Denoはサードパーティモジュールをダウンロードする際に、レスポンスにX-TypeScript-Typesヘッダが設定されていれば、そこで指定されたURLから型定義ファイルも一緒にダウンロードし、対象のJavaScriptモジュールへ適用してくれます。 ↩︎