Denoでimport maps使ってパッケージ管理

2020.08.06

What is deno?

巷で話題のTypeScript実行環境です。
Denoの基本やセットアップ方法については下の記事を参照。

About package manager for Deno

DenoではNode.jsにおけるnpmみたいなパッケージマネージャを持っていません。
もともと事前にモジュールをインストールする、
みたいな処理はいらず、実行時に必要なモジュールを取得します。

例えば下の例では、http/server.tsとdeno_structured_loggingをURL指定でimportしてます。

// main.ts
import { serve } from "https://deno.land/std/http/server.ts";
import { createLogger, consoleSink } from "https://deno.land/x/deno_structured_logging@0.4.2/mod.ts";

const logger = createLogger().addSink(consoleSink());

const server = serve({ port: 8000 });
logger.info("http://localhost:8000/");
for await (const req of server) {
  req.respond({ body: "Hello World\n" });
}

うごかしてみましょう。

$ deno run --allow-net main.ts
[2020-08-06T01:48:09.055Z INFO] http://localhost:8000/

# ブラウザでlocalhost:8000開くとハロワ表示

このように、URL指定(もしくはファイルパス指定)でモジュールをimportします。
これをみると、ソースにバージョンとか書いたりするのがいやな感じです。
この回避策として、Denoではimport-mapsという機能を使います。
※2020/8月時点ではunstable

import-mapsは下のようなJSON形式で定義します。
※ここでの名前はimport_map.json

{
  "imports": {
    "http/": "https://deno.land/std/http/",
    "log/": "https://deno.land/x/deno_structured_logging@0.4.2/"
  }
}

このimport-mapsを使うと、URLでimportしなくてもよくなります。
import-mapsの詳細はこことかで確認してください。

先程のmain.tsを少し修正。
import-mapsで定義したようにhttp/〜とかlog/〜といった感じに記述できます。

import { serve } from 'http/server.ts'
import { createLogger, consoleSink } from 'log/mod.ts';

const logger = createLogger().addSink(consoleSink());
const server = serve({ port:8000 });
logger.info("http://localhost:8000/");

for await (const req of server) {
  req.respond({ body: "Hello World\n" });
}

実行するときは--importmapオプションをつけてください。(--unstableも)

$ deno run --allow-net --importmap=import_map.json --unstable main.ts

これでモジュールの指定が1箇所にまとまり、少しわかりやすくなりました。

Summary

import mapsはまだunstableですし、すべての問題を解決するわけではありませんが、
とりあえずは使っておいたほうが良さそうです。

また、TrexのようなThird Party製の
パッケージ管理モジュールも開発されていますので、
今後はもっと管理が楽になるかもしれません。

Reference