📦

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