できない.dev

Node.js で「Error [ERR_REQUIRE_ESM]」が解消できない

ESM 専用パッケージを CommonJS の require() で読み込もうとすると ERR_REQUIRE_ESM になる。
動的 import() を await する、package.json を type:module に切り替える、または ESM 化前のバージョンに固定する。

#node#esm#commonjs#require#import

公開: 更新:

要約

Error [ERR_REQUIRE_ESM]: require() of ES Module ... not supported. は、require()ESM 専用 パッケージを読もうとして拒否された状態。まず Node のバージョンを確認する: require(esm)Node 20.19 / 22.12 以降では既定で有効になり、ESM を require() してもこのエラーは出ない。
それでも出るなら Node がこれより古いか、対象 ESM が top-level await を含む(その場合は別エラー ERR_REQUIRE_ASYNC_MODULE になる)。
確実な対処は動的 import() で、ほかに type:module 化・バージョン pin・Node の更新がある。

よくある原因

  1. ESM only への更新: chalk@5 / node-fetch@3 / nanoid@4 のように、メジャー更新で ESM only に切り替えたパッケージを CJS から require している。
  2. モジュール構文の混在: CJS 前提のプロジェクトで import 構文を混ぜているが、tsc / Babel の出力が require のまま。
  3. type 未指定: package.json"type":"module" が無いと Node は .js を CJS として扱う。
  4. Node が 20.19 / 22.12 未満: これらの版より前は require(esm) が既定で無効なため、ESM only を require した瞬間に ERR_REQUIRE_ESM になる。
    20.19 / 22.12 以降は既定で require できるが、対象 ESM が top-level await を含むと別エラー ERR_REQUIRE_ASYNC_MODULE に変わる。

解決策

1. 動的 import を await する

// CJS プロジェクトのまま、関数内で取り込む
async function main() {
  const { default: chalk } = await import("chalk");
  console.log(chalk.green("ok"));
}
main();

CJS のトップレベルでは await が使えないため関数で囲む。公式 ESM ドキュメント のとおり、動的 import() は ESM / CJS どちらからも呼べる唯一の橋渡し。

2. プロジェクトを ESM 化

package.json に追記する。

{
  "type": "module"
}

これで .js が ESM 扱いになり、import { x } from "pkg" がそのまま使える。require を残したいファイルだけ拡張子を .cjs に変える。

3. CJS 対応の最終版に pin

npm install chalk@^4

移行が間に合わない既存コードに対しては、ESM 化前の最終メジャーに固定する暫定策。^5 などに上げ直す前に、テストが通る状態を作る。

4. Node を 20.19 / 22.12 以降に上げる(require(esm) が既定で有効)

require(esm)(CJS から ESM を require() する機能)は Node 22.12.0 で unflag され、20.19.0 にもバックポートされて、現在は stable・フラグ不要で既定有効
これらの版に上げれば、ESM only パッケージも require() でそのまま読める(Node.js Modules ドキュメント)。

ただし対象の ESM(または依存)が top-level await を含む場合は、新しい Node でも require() できず ERR_REQUIRE_ASYNC_MODULE になる — このケースだけは Node を上げても解決しないので、解決策 1 の動的 import() を使う。
逆に旧来どおりの挙動に戻したい CI などでは、--no-experimental-require-module を付けると require(esm) を無効化できる。

実行例

実際に上記の手順を Node.js v20.20.2(Debian GNU/Linux 12 bookworm)環境で実行すると、素の require() は終了コード 0 で通る一方、--no-experimental-require-module を付けると ERR_REQUIRE_ESM(終了コード 1)が再現し、top-level await を含む ESM では新しい Node でも ERR_REQUIRE_ASYNC_MODULE(終了コード 1)が発生することが確認できる。

== versions ==
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
v20.20.2
v10.4.1
== run ==
--- Node.js バージョン ---
v20.20.2
--- npm install ---
npm install 終了コード: 0
--- 現行 Node: require(esm) が既定で有効なので素の require は通る ---
[Module: null prototype] {
  __esModule: true,
  default: 'hello from esm'
}
終了コード: 0
--- 旧挙動の再現: --no-experimental-require-module で ERR_REQUIRE_ESM ---
/tmp/tmp.woC4L30kHo/use-require.js:1
const pkg = require("esm-pkg");
            ^
 
Error [ERR_REQUIRE_ESM]: require() of ES Module /tmp/tmp.woC4L30kHo/esm-pkg/index.js from /tmp/tmp.woC4L30kHo/use-require.js not supported.
Instead change the require of index.js in /tmp/tmp.woC4L30kHo/use-require.js to a dynamic import() which is available in all CommonJS modules.
    at Object.<anonymous> (/tmp/tmp.woC4L30kHo/use-require.js:1:13) {
  code: 'ERR_REQUIRE_ESM'
}
 
Node.js v20.20.2
終了コード: 1
--- top-level await を含む ESM: 新 Node でも ERR_REQUIRE_ASYNC_MODULE ---
node:internal/modules/esm/module_job:433
      throw new ERR_REQUIRE_ASYNC_MODULE(filename, parentFilename);
      ^
 
Error [ERR_REQUIRE_ASYNC_MODULE]: require() cannot be used on an ESM graph with top-level await. Use import() instead. To see where the top-level await comes from, use --experimental-print-required-tla.
  From /tmp/tmp.woC4L30kHo/use-require-tla.js 
  Requiring /tmp/tmp.woC4L30kHo/esm-tla.mjs 
    at ModuleJobSync.runSync (node:internal/modules/esm/module_job:433:13)
    at ModuleLoader.importSyncForRequire (node:internal/modules/esm/loader:389:47)
    at loadESMFromCJS (node:internal/modules/cjs/loader:1363:24)
    at Module._compile (node:internal/modules/cjs/loader:1503:5)
    at Module._extensions..js (node:internal/modules/cjs/loader:1623:10)
    at Module.load (node:internal/modules/cjs/loader:1266:32)
    at Module._load (node:internal/modules/cjs/loader:1091:12)
    at Module.require (node:internal/modules/cjs/loader:1289:19)
    at require (node:internal/modules/helpers:182:18)
    at Object.<anonymous> (/tmp/tmp.woC4L30kHo/use-require-tla.js:1:13) {
  code: 'ERR_REQUIRE_ASYNC_MODULE'
}
 
Node.js v20.20.2
終了コード: 1
--- 万能策: 動的 import() を await で読み込む ---
動的 import の結果: hello from esm
終了コード: 0

— 2026-06-05 時点の出力

この記事は役立ちましたか?