About

ESM vs CommonJS — requireとimportが違う理由

同期ロード vs 非同期ロード、そして"type": "module"の意味

核心の違い

CJS:ランタイムロード — require()は関数呼び出し。条件付き可能。実行しながらロード。

ESM:パース時ロード — importは構文。トップレベルのみ。エンジンが実行前に依存性グラフを構築。

ESMからCJSをimport可能だが、CJSからESMをrequire不可(ESMは非同期、requireは同期)。

実戦での苦痛

ライブラリがESM onlyに転換するとCJSプロジェクトでrequire()不可。node-fetch v3、chalk v5がESM onlyになった時エコシステムに大混乱。

解決:dynamic import()でCJSからESMロード可能、ただしasyncになる。

キーポイント

1

CJS(require):同期、ランタイムロード、条件付き可能

2

ESM(import):非同期、パース時ロード、トップレベルのみ

3

ESM→CJS import可、CJS→ESM require不可(dynamic importで回避)

4

package.json "type": "module"でプロジェクト全体をESMに転換

ユースケース

新プロジェクト — ESMで始めるのが将来志向的 既存CJSプロジェクト — ESM onlyライブラリをdynamic importで使用
← Node.js Streams — 大容量データをメモリ爆発なしで処理する方法 Web Workers — JavaScriptでマルチスレッドを使う方法 →