Node.jsでCommonJSとESMの挙動を調べる
nodejsでコードを書いているとimoprtやrequireの使い分けがよくわからなかったので、使い分けを理解したかった。
以下の公式ドキュメントが参考になる。
Interoperability with CommonJS Modules: ECMAScript modules | Node.js v18.0.0 Documentation
imoprt statements
- importはESMとCJSをインポートできる。
- ただし、CJSはdynamic importでのみ対応している
package.jsonのtype=moduleの指定のありなし
- なし
- js拡張子はcjs扱い
- esmのファイルはmjs拡張子にする
- あり
- js拡張子はesm扱い
- cjsのファイルはcjs拡張子にする
ESMからCJSを読む
- できる
CJSからESMを読む
require("esm module")
はできない- importは制限付きというかdynamic importのみできる
const hoge = await import("esm.mjs")
みたいな。拡張子は省略できない。
export default
されてたモジュールは、defaultで参照できるconst { default as hoge } = await import("esm.mjs")
default
しかないモジュールでも{ default : xxxx }
という形でcjs側ではimportされる
// myEsmModule.mjs export const HOGE = "hoge"; export default { fuga : "fuga" } // cjs async function main() { const myModule = await import("./expEsm.mjs"); console.log(myModule); // { HOGE: 'hoge', default: { fuga: 'fuga' } } } main();
package.jsonは上位ディレクトリを確認し一番近いファイルのtypeが有効
package.json // type:module指定なし hoge.js // cjs module1 - package.json // type:module指定あり - fuga.js // esm