Node.js で「Error [ERR_REQUIRE_ESM]」が解消できない
ESM 専用パッケージを CommonJS の require() で読み込もうとすると ERR_REQUIRE_ESM になる。
動的 import() を await する、package.json を type:module に切り替える、または ESM 化前のバージョンに固定する。
要約
Error [ERR_REQUIRE_ESM]: require() of ES Module ... not supported. は、require() で ESM 専用 パッケージを読もうとして拒否された状態。
メジャー更新で ESM only に切り替わるライブラリが増えているため頻発する。
動的 import()、type:module 化、バージョン pin、Node 22 LTS の require(esm) の 4 択で対処する。
よくある原因
- ESM only への更新:
chalk@5/node-fetch@3/nanoid@4のように、メジャー更新で ESM only に切り替えたパッケージを CJS から require している。 - モジュール構文の混在: CJS 前提のプロジェクトで
import構文を混ぜているが、tsc / Babel の出力が require のまま。 - type 未指定:
package.jsonに"type":"module"が無いと Node は.jsを CJS として扱う。 - Node が古い: 20 以前は ESM 連携が部分的で、トップレベル await や条件付き export の動きが新しい LTS と違う。
解決策
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 22 LTS の require(esm) を試す
Node.js Modules ドキュメント によれば、22 LTS 以降は実験的に CJS から ESM の require がサポートされている(一部制約あり)。--experimental-require-module フラグの要否はマイナーバージョンで変化するため、リリースノートで現状を確認する。