ES ModulesとCommonJSの違い
インポート/エクスポートの方法が違う
CJSは require 関数と module.exports への代入で行う
code:cjs.js
const path = require("path");
module.exports.foo = () => console.log(Hello!);
ESMは import export という文法を使う
code:esm.js
import path from "node:path";
export const foo = () => console.log(Hello!);
ESMの import 文はファイル先頭にしか書けない
ESMでインポートを式として行うには dynamic import を使う
code:esm.dynamic.js
const path = await import("node:path");
CJSは同期的に読み込まれるが、ESMは非同期的に読み込まれる
ESMのdynamic importで Promise が返るのはこのため
ESMのインポートが非同期なのはこのため
Deno は標準ライブラリやその他ライブラリをURLインポートする code:deno.js
WebブラウザでESMを使う場合ももちろんURLでインポートする
code:browser.html
<script type="module" src="./index.js"></script>
デフォルトエクスポートの扱いが異なる
CJSは require() の返り値は module.exports の値と同じになる
エクスポートされた値がすべて含まれたオブジェクトが返る
ESMでデフォルトインポート import hoge from "" した場合の hoge は default という名前でエクスポートされた物体になる
複数あるエクスポート値のひとつが返るに過ぎない
ESMで「エクスポートされた値がすべて含まれたオブジェクト」を得る場合 import * as hoge する
CJSでは "use strict"; がないとstrictモードにならないが、ESMでは必ずstrictモードになる