ES Modules がデファクトスタンダードになりつつある。
最近の環境なら基本的には ES Moduels で問題ない。
一部 CommonJS じゃないと実行できない環境や、ライブラリ開発の場合は対応が必要になることもあるかもしれない。
元々 JavaScript はウェブページに動きをつけたりするための言語で、ブラウザー上で動作する言語として生まれた。
JavaScript の実行にはインラインスクリプトとして記述するか、スクリプトタグで JavaScript ファイルを読み込む方法があるが、これには以下のような問題があった。
- グローバルスコープが汚染される
- script タグの順序が読み込みに影響し、依存関係が複雑になる
- 複数の JavaScript ファイルの読み込みを JavaScript のみで完結出来ず、HTML と密結合になる
IIFE (即時実行関数式) によってグローバル汚染は防ぐことが出来るが、JQuery のように$
というグローバル変数の定義は必要になる。
また、依存関係の問題は解決出来ない。
モジュールシステムとは、JavaScript で他の JavaScript ファイルを読み込むためのシステムのことであり、いくつかの仕様がある。
- CommonJS
- ウェブブラウザ以外の環境で実行するために作られたプロジェクト
- ServerJS → CommonJS
- Node.js のデフォルト
- AMD
- Asynchronous Module Definition
- 非同期モジュールの仕様
- CommonJS の仕様の一部だったが独立した
- 実装はRequireJS
- WebPack や Browserify で良いやんってなった
- Asynchronous Module Definition
- UMD
- Universal Module Definition
- 環境関係なく動作するモジュール仕様
- if 文で頑張る
- ES Modules(ECMA Script)
- European Computer Manufacturers Association
- 欧州電子計算機工業会
- TC39 で仕様策定してる
- Node.js でも v16 からサポート
- European Computer Manufacturers Association
- 8.5.0 でサポート開始
- 12.17.0 で experimental フラグを削除
- 12.22.0 で stable 判断
CommonJS と ES Modules の大きな違いは Top-level await が可能かどうかである。 そのため CommonJS は同期的に、ES Modules は非同期的に読み込まれる。
import や require を使って読み込むことが可能。
ES Modules は非同期で読み込まれるため、dynamic import を使う。
もちろん、CommonJS は Top-level await に対応していないので、非同期関数内で読み込む必要がある。
const moduleOfES = await import("./module.mjs");
package.json に"type": "module"
を指定することで.js
ファイルは ES Modules として扱われる
デフォルトを ES Modules にした場合は、CommonJS は.cjs
の拡張子を使う必要がある。
また、import path は下記のようにファイル名と拡張子を省略出来なくなる。
import add from "./esm/libs/calc.js";
TypeScript で書いている場合も、.ts
や.tsx
ではなく.js
や.jsx
で記述する。
デフォルトは"type": "commonjs"
で、この場合は ES Modules の拡張子を.mjs
にする必要がある。
調べてる途中で面白かったやつ
Top-level await と dynamic import でデッドロックを作る
https://qiita.com/uhyo/items/0e2e9eaa30ec2ff05260#循環参照がある場合-4-dynamic-importでデッドロックを作る
<script type="importmap">
https://developer.mozilla.org/ja/docs/Web/HTML/Element/script/type/importmap
Rails 7.0 で標準になった importmap-rails とは何なのか?
https://zenn.dev/takeyuwebinc/articles/996adfac0d58fb
MDN JavaScript モジュール
https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Modules
ECMA Script
https://ja.wikipedia.org/wiki/ECMAScript
JavaScript History
https://www.w3schools.com/js/js_history.asp
IIFE (即時実行関数式)
https://developer.mozilla.org/ja/docs/Glossary/IIFE
JavaScript の Module System の歴史
https://scrapbox.io/tasuwo/JavaScript_%E3%81%AE_Module_System_%E3%81%AE%E6%AD%B4%E5%8F%B2
CommonJS
https://ja.wikipedia.org/wiki/CommonJS
v8 JavaScript モジュール https://v8.dev/features/modules
JavaScript の Module System の歴史 https://scrapbox.io/tasuwo/JavaScript_%E3%81%AE_Module_System_%E3%81%AE%E6%AD%B4%E5%8F%B2
CommonJS と ES Modules についてまとめる https://zenn.dev/yodaka/articles/596f441acf1cf3