📦
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で使用