Deno 2 で npm パッケージが動かない・import エラーになる時の原因と対処法【npm: specifier / node: 組み込みモジュール】

公開日:2026-09-15/カテゴリ:Deno・Node.js・TypeScript/AnchorUp 技術ブログ

Deno 2 で npm パッケージが動かない症状

Deno 2 にアップグレードしたとき、または Node.js プロジェクトを Deno に移行しようとしたとき、こんなエラーに遭遇したことはないですか?

error: Module not found "express".
error: Cannot find module 'fs'
error: Relative import path "lodash" not prefixed with / or ./

Deno はブラウザ互換の ESモジュールを採用しており、Node.js とはモジュール解決の仕組みが根本的に異なります。この違いを理解すれば、ほとんどのエラーは数分で解決できます。

原因一覧

症状 原因 対処法
Module not found "express" npm: プレフィックスがない npm:express と書く
Cannot find module 'fs' node: プレフィックスがない node:fs と書く
CJS モジュールが動かない CommonJS 専用パッケージ 互換パッケージを探す or ワークアラウンド
PermissionDenied エラー Deno のパーミッション制限 --allow-* フラグを追加
ネイティブアドオンがクラッシュ N-API バインディング非対応 代替パッケージを使う

なぜ Deno は Node.js と import の書き方が違うのか

Deno は設計上「URL や明示的なパスでのインポート」を原則としています。Node.js の require('express') のような「ベア(bare)スペシファイアー」でのインポートは、Deno にとってはデフォルトでは意味を持ちません。

Deno 2 では Node.js との互換性が大幅に強化されましたが、明示的に「このモジュールは npm から取得する」「これは Node.js 組み込みモジュールだ」と宣言する必要があります。それが npm: と node: というプレフィックスです。

対処法1:npm: プレフィックスを使う

npm パッケージには必ず npm: プレフィックスを付けてください。

// ❌ 動かない(Node.js のベアスペシファイアー)
import express from 'express'
import _ from 'lodash'
import { z } from 'zod'

// ✅ 動く(Deno の npm: スペシファイアー)
import express from 'npm:express@4'
import _ from 'npm:lodash'
import { z } from 'npm:zod'

バージョンは省略可能ですが、再現性のためにピン留めすることを推奨します。

// バージョン指定あり(推奨)
import { Hono } from 'npm:hono@4'
import { drizzle } from 'npm:drizzle-orm@0.36.0/node-postgres'

対処法2:node: プレフィックスで組み込みモジュールを使う

Node.js 組み込みモジュール(fs、path、crypto 等)は node: プレフィックスが必要です。

// ❌ 動かない
import { readFileSync } from 'fs'
import path from 'path'
import { createHash } from 'crypto'

// ✅ 動く
import { readFileSync } from 'node:fs'
import path from 'node:path'
import { createHash } from 'node:crypto'

node: プレフィックスなしのベアスペシファイアーは、deno.json で nodeModulesDir を設定すれば使えるようになります(後述)。

対処法3:package.json を使ってベアスペシファイアーを有効にする

既存の Node.js プロジェクトをそのまま Deno で動かしたい場合は、package.json と deno.json を組み合わせる方法が有効です。

deno.json の設定:

{
  "nodeModulesDir": "auto"
}

"nodeModulesDir": "auto" を設定すると、package.json の dependencies を読んで node_modules/ を生成するため、ベアスペシファイアーがそのまま動きます。

deno install   # node_modules を生成
deno run main.ts

これにより、既存の Node.js コードを大幅に変更せずに Deno で実行できます。

対処法4:import map でエイリアスを設定する

deno.json の imports セクションでエイリアスを定義すれば、ファイルの先頭をすっきりさせられます。

{
  "imports": {
    "express": "npm:express@4",
    "lodash": "npm:lodash",
    "zod": "npm:zod",
    "fs": "node:fs",
    "path": "node:path"
  }
}
// deno.json の imports を使えばプレフィックスなしで書ける
import express from 'express'
import { z } from 'zod'
import { readFileSync } from 'fs'

大規模なプロジェクトではこの方法が最もメンテナンスしやすいです。

対処法5:パーミッションエラーへの対応

Deno はセキュリティファーストな設計のため、ファイルシステム・ネットワーク・環境変数へのアクセスには明示的なパーミッションが必要です。

Uncaught PermissionDenied: Requires net access to "api.example.com"
# 必要なパーミッションを指定して実行
deno run --allow-net --allow-read --allow-env main.ts

# 開発中は全パーミッションを許可する(本番は非推奨)
deno run --allow-all main.ts
フラグ 許可する操作
--allow-net ネットワークアクセス
--allow-read ファイル読み取り
--allow-write ファイル書き込み
--allow-env 環境変数へのアクセス
--allow-run サブプロセスの実行
--allow-all 全パーミッション(-A でも可)

CommonJS 専用パッケージが動かない場合

一部の古い npm パッケージは CommonJS 形式のみで提供されており、Deno との互換性に問題が生じることがあります。

error: Cannot load CJS module "some-package"

対処法:

  1. ESM 版があるか確認する:"some-package/esm" や "some-package-esm" のような ESM ビルドを探す
  2. npm:some-package で試す:Deno の npm サポートは CJS を自動変換する場合がある
  3. 代替パッケージを使う:例えば moment の代わりに npm:dayjs(ESM 対応)を使う

よくある環境変数まわりのエラー

Node.js では process.env.API_KEY が一般的ですが、Deno では Deno.env.get('API_KEY') が推奨されます。ただし process.env も Deno 2 ではサポートされています。

// Deno ネイティブな書き方
const apiKey = Deno.env.get('API_KEY')

// Node.js 互換の書き方(Deno 2 でも動く)
const apiKey = process.env.API_KEY

--allow-env を渡し忘れると PermissionDenied になるので注意してください。

まとめ

問題 解決策
npm パッケージが見つからない npm:パッケージ名 プレフィックスを付ける
Node.js 組み込みが動かない node:fs のように node: を付ける
ベアスペシファイアーをそのまま使いたい deno.json で "nodeModulesDir": "auto" + deno install
プレフィックスなしで書きたい deno.json の imports でエイリアスを設定
パーミッションエラー --allow-net 等のフラグを追加

Deno 2 は Node.js との互換性を大幅に改善しており、既存の npm エコシステムをほぼそのまま使えます。「npm: と node: プレフィックス」という基本ルールを押さえれば、移行コストは想像より低いはずです。

既存プロジェクトの移行には "nodeModulesDir": "auto" から始めて、徐々に Deno ネイティブな書き方に移行するのがスムーズです。

技術ブログの記事一覧へ