LabHub

ブログ

Deno 2と3 深掘り 2026 — Node互換の時代、JSR・Fresh 2・Deno KVの現在地(ランタイムの賭けはどこに着いたか) 日本語

한국어English日本語

プロローグ — Ryan Dahl の二度目の自己否定

Ryan Dahl は 2009年に Node を作り、2018年の JSConf EU で「Node について後悔している10のこと」という有名な発表をした。そして Deno を作った。デフォルト deny のセキュリティ、TS は一級市民、依存は URL import、package.json は存在しない — すべてが Node に対する明示的な回答だった。

ところが 2024年9月、Deno 2 が出た。最大の変化は自己否定だ。

Deno が当初拒んだ Node の設計判断のほぼ全てを、6年を経て受け入れた。プライドを呑んで。

これは退却なのか、進化なのか。両方だ。理想主義から実用主義への転換であり、同時に JS エコシステムの現実(npm は消えない)を認めた賭けでもある。

本稿は Deno 2 リリース後およそ20ヶ月、2026年5月時点で Deno の賭けがどこまで来たか、Bun・Node 22+ との三つ巴はどう収束したか、セキュリティモデル・JSR・Fresh 2・Deno KV が現実のどこに位置づいているかを整理する。


1章 · Deno 2 の核 — Node 互換がデフォルトになる

Deno 1 の世界観、その限界

Deno 1 は純粋な世界を描こうとした。

問題は単純だった。JS 世界の 90% は既に npm の上にあった。Express, React, Prisma, AWS SDK, Sentry, Stripe SDK — すべて npm。Deno は早期に npm: specifier を互換シムとして追加したが、本格 production に持っていくには足りなかった。package.json に書かれた依存をそのまま読めず、node_modules を触るフルスタック・ツールが壊れ、モノレポのワークフローが不格好だった。

Deno 2 の答えは明快だ。「Node のやり方でも動く」

何が変わったか(2024年9月)

# Deno 2 — 既存の Node プロジェクトから
deno install            # package.json を読み node_modules を生成
deno run npm:express    # npm パッケージを直接実行
deno task dev           # package.json の scripts.dev を実行
領域Deno 1Deno 2
package.json無視 / 部分対応一級 — deno install が読む
node_modules意図的に無しオプション — nodeModulesDir: auto
npm パッケージnpm: specifier同上 + package.json から自動
deno installURL ベースのバイナリ installNode 互換パッケージマネージャ
deno run npm:foo部分対応安定、広い互換
workspaceなし一級 — deno.jsonworkspace フィールド

Deno 2 のモットーはもはや「Node を置き換える」ではない。「Node と Deno の摩擦を限りなくゼロに近づける」だ。

マイグレーションは楽になったか

既存の Node プロジェクトをそのまま Deno で動かすと:

最初の1年で摩擦が大きかったのは ネイティブアドオン(sharp, canvas, bcrypt-native などの C++ バインディング)で、2025年を通じて N-API 互換は段階的に良くなった。2026年中盤時点で、一般的な npm パッケージの90%以上は Deno 2 でほぼ問題なく動く。


2章 · deno install — npm 互換のパッケージマネージャ

二つのモード

deno install は二つのモードで動く。

# グローバル binary インストール(Deno 1 から)
deno install -gA --name lint jsr:@std/cli/parser

# プロジェクト依存のインストール(Deno 2 で新規)
deno install            # package.json を読み node_modules を生成
deno install --add npm:express@4   # 新しい依存を追加
deno install --add jsr:@hono/hono  # JSR の依存を追加

二つ目のモードがパラダイム転換だ。npm install, pnpm install, yarn install をそのまま置換できるコマンドになった。

速度と lockfile

hot cache, 約500依存:
  npm install:    14s
  pnpm install:    4s
  bun install:     1.3s
  deno install:    2.1s

bun install ほど速くはないが、pnpm install より速く、npm install よりはるかに速い。lockfile は deno.lock(テキスト JSON)で、最初から diff-friendly に設計されている。Bun が binary lockfile で一度つまずいた点と対照的だ。

node_modules モード

// deno.json
{
  "nodeModulesDir": "auto",   // または "manual" または false
  "lock": true
}

auto にすると package.json を読んで自動的に node_modules を作る。manual は npm/pnpm/yarn で作られた既存の node_modules をそのまま使う(大きなモノレポ移行のシナリオ)。false だと Deno 1 スタイルのグローバルキャッシュのみ。

このオプションが存在すること自体が、理想主義を脇に置き実用主義を選んだ証拠だ。


3章 · deno run で npm パッケージを直接実行

npm: specifier の進化

Deno 2 のモットーの一つは「追加設定なしで npm パッケージを import する」だ。

// app.ts
import express from "npm:express@4";
import { z } from "npm:zod";
import OpenAI from "npm:openai";

const app = express();
app.get("/", (_, res) => res.json({ ok: true }));
app.listen(3000);
deno run --allow-net --allow-read --allow-env app.ts

これがそのまま動く。package.json も不要、node_modules も不要(グローバルキャッシュに取得される)。Bun と Node が package.json を必須とするのに比べ、単一ファイルのスクリプトは Deno が一番滑らかだ。

Bun と Node との比較

# 単一ファイルのスクリプトに npm 依存

# Deno
deno run --allow-net script.ts

# Bun
bun script.ts            # bun add が必要、または inline shebang のトリック

# Node
npm init -y && npm i express && node script.js

クイックスクリプト + npm 一つ二つ」の領域では Deno の DX が優勢だ。Deno 1 からの強みが Deno 2 でも生きている。


4章 · JSR — JavaScript Registry の賭け

なぜまた別のレジストリ

JSR(jsr.io)は Deno チームが 2024年初に立ち上げた新しい JavaScript レジストリだ。npm が既にあるのになぜ?

JSR の主張:

  1. TS-native publishing — TS ソースをそのまま publish。利用側がビルドツールを選ぶ。(npm は通常コンパイル済み JS + .d.ts。)
  2. 標準 ESM のみ — CJS なし、package.json の迷路なし。
  3. ランタイム非依存 — Deno だけでなく Node・Bun・ブラウザから import 可能。
  4. 品質スコア — ドキュメント・テスト・型の充実度を score で表示。
  5. scope が一級@scope/package モデルが基本。

使い方

// そのまま import
import { parse } from "jsr:@std/cli/parser";
import { Hono } from "jsr:@hono/hono";
# package.json スタイル
deno install --add jsr:@hono/hono
# Node からも使える
npx jsr add @hono/hono
# または直接 — ビルド済み形式で取得

採用の現実 — 2026 mid

カテゴリJSR 採用
Deno 1st-party @std ライブラリ100% — @std の新ホーム
Deno エコシステムのツール広範 — Hono, Fresh, Oak など
一般 JS ライブラリゆっくり — npm にも並行公開する場合が多い
ユーザー数npm のごく一部 — ただし急速に成長

JSR は「npm を殺す」ではなく、「TS-first の別の選択肢を作る」だ。一定程度成功した — Deno エコシステム内では standard、外では niche。

JSR が変えたこと

npm 側の反応

興味深いディテール。Deno は 2024年に npm CLI のBSD ライセンスのフォークを作った — 名前は "npm" ではなく別名で(コミュニティガイドラインに従う形)。これが小さなライセンス・ネーミング論争を生んだが、npm Inc. から大きな法的反応はなかった。最終的なメッセージは「npm 互換が優先、敵対は二の次」だ。


5章 · Fresh 2 — アイランド・アーキテクチャの第2ラウンド

Fresh 1 の約束

Fresh は Deno の公式フルスタック・フレームワークだった。中核のコンセプト:

優れた賭けだったが、1.x の時期は ルーティングモデルの限界(file-based + ハンドラ分離)と React エコシステム互換の不在が採用を制限した。

Fresh 2 が変えたもの

// routes/api/hello.ts (Fresh 2 スタイル)
import { define } from "$fresh/server.ts";

export const handler = define.handlers({
  async GET(ctx) {
    return new Response(JSON.stringify({ msg: "hello" }), {
      headers: { "content-type": "application/json" },
    });
  },
});
// routes/index.tsx
import { define } from "$fresh/server.ts";
import Counter from "../islands/Counter.tsx";

export default define.page<{ now: string }>((props) => (
  <main>
    <h1>現在時刻: {props.data.now}</h1>
    <Counter start={0} />
  </main>
));

Fresh 2 の主な変更:

Fresh が採用で追いつけなかった理由(率直に)

Fresh 2 は Deno Deploy に紐づくフルスタックならとても良い選択。だがフルスタックの default になる道は狭い。


6章 · Deno KV — 内蔵 KV が production-ready に

Deno KV の正体

Deno KV は Deno ランタイムに内蔵されたキー・バリュー・ストアだ。SQLite に似た単一ノードモードと、Deno Deploy 上でのグローバル分散モードがある。

// kv.ts
const kv = await Deno.openKv();

// set
await kv.set(["users", "alice"], { name: "Alice", joined: Date.now() });

// get
const result = await kv.get<{ name: string }>(["users", "alice"]);
console.log(result.value?.name);  // "Alice"

// list (prefix query)
for await (const entry of kv.list({ prefix: ["users"] })) {
  console.log(entry.key, entry.value);
}

// atomic transaction
await kv.atomic()
  .check({ key: ["counter"], versionstamp: null })
  .set(["counter"], 1)
  .commit();

2026 時点の状態

側面状態
Local (SQLite-backed)GA (production-ready)
Deno Deploy (FoundationDB-backed, グローバル)GA
クロスリージョン複製自動
Atomic transactions対応
Queue API対応 (kv.enqueue)
Watch API対応 — リアルタイム購読
制限キーあたり 64KB の値、一部プラン制限

Deno KV は Cloudflare KV や Workers KV の位置を狙ったが、Deno エコシステムに縛られている分ポジショニングは厳しい。それでも「一行で始められる分散 KV」というスローガンは本当に成立している。

よく使われる場面

弱い領域


7章 · workspace — Deno のモノレポ回答

モノレポが一級市民に

Deno 2 で deno.jsonworkspace フィールドが追加された。

// ルートの deno.json
{
  "workspace": [
    "./packages/api",
    "./packages/web",
    "./packages/shared"
  ],
  "tasks": {
    "dev": "deno task --filter=* dev"
  }
}
// packages/api/deno.json
{
  "name": "@app/api",
  "version": "0.1.0",
  "exports": "./mod.ts",
  "tasks": {
    "dev": "deno run --watch --allow-net mod.ts"
  }
}

内部パッケージを import { foo } from "@app/shared" で import 可能。pnpm workspace や Bun workspace とほぼ同じモデルだが、Deno の lockfile/キャッシュ統合のおかげでインストール時間は非常に短い。

Turborepo・Nx との比較

ツール強み弱み
Deno workspaceゼロ設定、lockfile 統合、install 速いtask オーケストレーションが単純
pnpm workspace広い互換、誰でも慣れているinstall は Deno より遅い
Turborepoビルドキャッシュ、強力なグラフ設定の重み
Nx強力な generator、大規模モノレポ標準学習曲線が険しい

Deno workspace は小〜中規模モノレポで滑らか。ビルドグラフキャッシュが必須になる大規模モノレポは Turborepo/Nx をそのまま使う方が安全。


8章 · セキュリティモデル — なお殺し技

最初から最後まで生き残った差別化要因。デフォルト deny

permission flag 一覧

deno run script.ts                    # ほぼ何もできない
deno run --allow-read script.ts       # ファイル読込
deno run --allow-net script.ts        # ネットワーク
deno run --allow-env script.ts        # 環境変数
deno run --allow-write=./data script.ts   # 特定ディレクトリのみ書き込み

# Deno 2 以降: より細かいスコープ
deno run --allow-net=api.example.com,db.internal:5432 script.ts
deno run --allow-env=DATABASE_URL,REDIS_URL script.ts

運用での実際の意味

良い点:

摩擦:

Deno 2 のセキュリティ改善

セキュリティモデルは 2025〜2026 年にかけてソフトウェア・サプライチェーン攻撃が増えたことで価値が上がった領域だ。xz-utils 事件、npm の event-stream 事件以降、「デフォルト deny」を真面目に考える会社が増えた。


9章 · Deno 3 はどこにあるか

2026 mid 時点の状況

Deno 3 は 公式リリース前だ(2026年5月時点)。ロードマップ記事と RFC の議論から、次の方向が見える。

本当に大きな次の賭けが出るのか、段階的アップグレードに留まるのかはまだ決まっていない。Deno 2 が大きな自己否定だった分、Deno 3 は保守的な evolution の可能性が高い。


10章 · Deno vs Bun vs Node 22+ — 三つ巴の整理

2026 mid 時点のポジション

Node 22+BunDeno 2
採用1位(圧倒的)2位(開発ツール中心)3位(特定領域)
Cold start35〜60ms10〜20ms25〜40ms
Node 互換100%(本人)90〜95%90〜95%(Deno 2 以降)
TS native--experimental-strip-typesゼロ設定ゼロ設定
セキュリティモデル標準(全許可)標準デフォルト deny
標準ライブラリ大きなコア小さい豊富な @std
パッケージマネージャnpm/pnpm/yarnbun installdeno install
レジストリnpm のみnpm のみnpm + JSR
フルスタック・フレームワークNext/Astro/Remix(Node 上のものをそのまま)Fresh 2
内蔵 KVなしbun:sqliteDeno KV
Edge デプロイVercel/NetlifyCloudflare Workers は別 isolateDeno Deploy
AI エージェント sandbox可能(手動)可能非常に適合(権限モデル)

意思決定ガイド

Deno 2 が合う場面:

  1. AI エージェントのサンドボックス — モデル生成コードを権限制限して実行。この領域で Deno は明確に1位。
  2. 高セキュリティ / 政府 / 金融の一部ワークロード — permission モデルが audit 追跡で意味を持つ。
  3. 新規プロジェクトの素早いプロトタイプ — 単一ファイル + npm 依存が最も滑らか。
  4. Deno Deploy 上の小さなフルスタック — Fresh 2 + Deno KV。
  5. @std 中心のバックエンド・ツール — 標準ライブラリの安定性が魅力。

Bun が合う場面:

  1. CI 速度(bun install, bun test)。
  2. CLI ツール(bun build --compile)。
  3. Edge の cold start。
  4. SQLite ヘビーな小規模サービス。

Node 22+ が依然合う場面:

  1. 大半のエンタープライズ production。
  2. APM/observability が重要な環境。
  3. ネイティブアドオンを抱える大規模モノレポ。
  4. 会社標準ランタイム — 採用しやすい。

三つのランタイムは zero-sum ではない。一つの会社で Node(メインサービス)、Bun(CLI/CI)、Deno(AI エージェント sandbox、高セキュリティ部分)を併用するパターンが増えている。「どれか一つが全勝」という narrative は 2026 年にはもう合わない。


11章 · npm 互換の broken / over-delivered 領域

Over-delivered

Broken / 依然弱い


12章 · 誰が production で Deno 2 を使っているか

ケース A — AI エージェントの sandbox

最も明確な win 領域。モデル生成コードを権限制限して実行したい環境:

ケース B — Deno Deploy 上のフルスタック

Fresh 2 + Deno KV による小さなフルスタック:

ケース C — 標準ライブラリ重視のバックエンド・ツール

@std/cli, @std/path, @std/fs, @std/encoding を多用する CLI / dev tool。外部依存を最小化する価値があるところ。

ケース D — Slack/Discord ボット、webhook ハンドラ

Deno.serve + Deno.openKv() による小さな webhook サービス。権限モデルで爆発半径を狭め、グローバル展開は Deno Deploy で。

ケース E — ほぼ無し — 大規模エンタープライズ・モノリス

Bun と同じ理由。APM、デバッガ、人の慣れ、既存コードベースの重み。

名前のついた事例(公開情報ベース)


13章 · マイグレーション — Node プロジェクトを Deno 2 へ

段階的な導入

  1. deno fmtdeno lint のみ導入 — 他ツールの変更なし。摩擦が少ない最初の一歩。
  2. CI で deno test — Vitest/Jest と並行。Deno test の速度とゼロ設定 TS の魅力を確認。
  3. 単一スクリプトを Deno へscripts/migrate.ts のようなワンオフから。
  4. 新規小サービスを Deno で書く — 新マイクロサービス / 内部ツール。
  5. deno install で依存管理 — Node ランタイムを保ちつつ install だけ Deno に。
  6. production ランタイムを Deno に — 最大の一歩、最後。

導入チェックリスト

よくある anti-pattern


エピローグ — 理想主義から実用主義へ

Deno 1 は Node への明示的反論として生まれた。Deno 2 はその反論の半分を撤回し実用主義を選んだ。結果:

Deno は「Node を置き換える」 narrative を諦め、代わりに「Node の隣に意味ある居場所を作る」 narrative に移った。 その居場所が AI エージェント sandbox、Deno Deploy、標準ライブラリ中心のツールだ。

覚えておくべきこと:

導入チェックリスト(Deno を入れる前)

よくある anti-pattern(再強調)

次回予告


参考 / References

Deno 公式

Deno 2 リリース資料

JSR

Fresh

Deno KV

Deno Deploy

Node.js (比較)

Bun (比較)

セキュリティ / 権限モデル

運用採用事例(公開記事ベース)

批判的視点 / 回顧

標準化 / WinterCG


コメント

まだコメントはありません。

ログインするとコメントできます