Deno 2:node_modules不要、高セキュリティ、Node.js互換のREST APIを構築する

Development tutorial - IT technology blog
Development tutorial - IT technology blog

「node_modules」という名の悪夢と設定の混乱

想像してみてください。シンプルなAPIを1つ書きたいだけなのに、node_modulesフォルダが400MBものディスク容量を占有してしまうことを。私はかつて5万行のコードを持つプロジェクトをリファクタリングしたことがあります。tsconfig.jsonの依存関係のアップグレードや競合の修正だけで、丸3日間を費やしました。さらに、eslintやprettierjestといったツールを、大量の煩雑な設定ファイルとともにインストールしなければならない手間もありました。

Node.jsは非常に強力ですが、多くのレガシーな負債を抱えています。セキュリティ面では、Node.jsはデフォルトで、あらゆるパッケージが許可なくディスクや環境変数にアクセスすることを許してしまいます。サプライチェーン攻撃(supply chain attacks)が急増している昨今、これは真に懸念すべき脆弱性です。

Deno 2はNode.jsに欠けているものをどう解決するのか?

Node.jsとDenoの両方の生みの親であるRyan Dahl氏は、過去の過ちを修正するためにDeno 2を設計しました。最大のハイライトは「オールインワン」の体験です。TypeScriptを実行するためにtscをインストールする必要も、コードを整形するためにprettierを入れる必要もありません。すべてが最初から組み込まれています。

特に、Deno 2は現在、npmエコシステムと非常に高い互換性を持っています。障害を感じることなく、expressmongooseをすぐにプロジェクトに取り入れることができます。Node.jsの複雑なモジュールチェック手順が省略されているため、起動速度も大幅に向上しています。

Deno 2を爆速でインストールする

複雑なインストール手順は忘れてください。LinuxまたはmacOSなら、以下のコマンドを1つ実行するだけです:

curl -fsSL https://deno.land/x/install/install.sh | sh

deno --versionと入力して確認してください。バージョン2.xが表示されれば、最新のモダンなランタイムを体験する準備は完了です。

REST APIの構築:設定不要、node_modules不要

server.tsファイルを作成しましょう。設定ファイルは一切使わず、純粋なTypeScriptを使用します。

// server.ts
const kv = await Deno.openKv(); // 組み込みのKey-Valueデータベース

interface User {
  id: string;
  name: string;
}

Deno.serve(async (req) => {
  const url = new URL(req.url);
  const path = url.pathname;

  // ユーザー一覧の取得
  if (path === "/users" && req.method === "GET") {
    const users = [];
    for await (const res of kv.list({ prefix: ["users"] })) {
      users.push(res.value);
    }
    return Response.json(users);
  }

  // 新規ユーザーの追加
  if (path === "/users" && req.method === "POST") {
    const body = await req.json();
    const id = crypto.randomUUID();
    const newUser = { id, ...body };
    await kv.set(["users", id], newUser);
    return Response.json(newUser, { status: 201 });
  }

  return new Response("Not Found", { status: 404 });
});

大きな違いは、npm installを実行する必要がない点です。Denoが自動的にモジュールを管理・キャッシュするため、プロジェクトフォルダは常にクリーンな状態に保たれます。

サンドボックス・セキュリティ機構:権限をコントロールする

これは私が最も気に入っている機能です。もしdeno run server.tsコマンドを実行すると、ネットワークアクセス権限を与えていないため、Denoは即座に実行をブロックします。APIを動作させるには、明示的に指定する必要があります:

deno run --allow-net --allow-read --allow-write server.ts

この「明示的な権限付与(explicit permissions)」というアプローチは非常に安全です。もしサードパーティのライブラリにデータを盗もうとする悪意のあるコードが含まれていても、許可を与えない限りDenoがその挙動を封じ込め、安全を確保します。

Deno 2でnpmライブラリを使用する

Deno 2は、npm:プレフィックスを使用することでライブラリ不足の壁を取り払いました。使い慣れたExpressを使いたい場合は、以下の例を見てください:

import express from "npm:express@5";
const app = express();

app.get("/", (req, res) => {
  res.send("ExpressがDeno 2上でスムーズに動作しています!");
});

app.listen(3000);

システムが自動的にExpressをキャッシュにダウンロードします。煩わしいpackage.jsonも不要で、プロジェクトごとにディスク容量を消費することもありません。

実践的な知見:いつDeno 2へ移行すべきか?

新しいマイクロサービスを構築したりCLIツールを作成したりする場合、Deno 2は最良の選択肢です。設定ファイルを排除できるため、プロトタイピングのスピードが2倍になります。ただし、Node.jsのネイティブC++ライブラリに深く依存している古いプロジェクトの場合は、移行前に互換性を十分に確認することをお勧めします。

私が得た最大の教訓は、「最高のテクノロジーとは、インフラではなくロジックに集中させてくれるもの」だということです。Deno 2はまさにその証明です。私の多くの実プロジェクトにおいて、ビルド時間を3分から30秒に短縮してくれました。

Deno Taskによるワークフローの最適化

package.json内のscriptsを使う代わりに、Denoではより洗練されたdeno.jsonファイルを使用します:

{
  "tasks": {
    "dev": "deno run --allow-net --watch server.ts",
    "start": "deno run --allow-net server.ts"
  }
}

deno task devと入力するだけで、コードを変更したときにサーバーが自動的にリロードされます。非常に便利です!

結論:まずは小さなスクリプトから始めよう

巨大なシステム全体をいきなりDenoに移行しようと急ぐ必要はありません。まずは自動化スクリプトや、小さな補助サービスから試してみてください。node_modulesの混乱から解放される心地よさを実感できるはずです。バージョン2になり、導入の障壁はほぼゼロになりました。ぜひ今日からインストールして試してみてください!

Share: