
ES Modules(ESM)は、ECMAScript 2015(ES6)で正式に言語仕様に組み込まれたJavaScriptの公式モジュールシステムです。それまでJavaScriptは言語自体にモジュール機能を持たず、ブラウザではグローバル変数の汚染と戦い、Node.jsではCommonJSが事実上の標準として使われてきました。ES Modulesはimport文とexport文という宣言的な構文でモジュールの依存関係を表現し、静的解析を可能にする画期的な仕様です。現在ではブラウザ、Node.js、Deno、Bunのすべてがネイティブサポートし、Tree Shakingやコード分割の前提となっています。
この記事の目次
- ESM登場以前の混迷
- import/export構文の特徴
- ブラウザとNode.jsでの実装
- ESMが当たり前になる時代の設計
- まとめ
ESM登場以前の混迷

1995年に生まれたJavaScriptは、長らくモジュールという概念を持たない言語でした。Web開発ではscriptタグでJSファイルを並べ、グローバル変数を介して機能を共有するスタイルが当たり前で、規模が大きくなると名前衝突や読み込み順序の問題が深刻になります。これに対応するため、IIFEや名前空間オブジェクト、AMD(RequireJS)、CommonJS(Node.js)など、ユーザーランドでのモジュール記述法が乱立する状態が長く続きました。
ES Modulesは、こうした混乱を言語仕様レベルで解消する目的で2015年に標準化されました。策定議論にはMozilla、Google、AppleなどのブラウザベンダーとNode.jsコミュニティが参加し、ブラウザとサーバの両方で同じモジュール仕様を共有することが目標とされました。実装と仕様の進化に時間はかかりましたが、現在では事実上の唯一の標準モジュールシステムとなっています。
import/export構文の特徴

ES Modulesは、export文で公開する識別子を宣言し、import文で別ファイルから読み込みます。重要な特徴はこれらが静的構文であり、トップレベルにしか書けない点です。解析時に依存関係グラフを確定できるため、バンドラはどの関数が使われていないかを推論でき、未使用コードを除去するTree Shakingが成立します。CommonJSの動的なrequireでは難しかった最適化です。
また、ESMのインポートは「ライブバインディング」と呼ばれる仕組みを持ち、エクスポート側の値が変わるとインポート側も即座に更新されます。これはオブジェクトのプロパティをコピーするCommonJSとは挙動が異なり、循環依存に対する振る舞いも変わります。ESMに移行する際は、こうしたセマンティクスの差を意識しないと予期せぬバグを生むので注意が必要です。
ブラウザとNode.jsでの実装

ブラウザ側ではと書くことでESMを直接ロードできます。型属性なしのscriptと異なり、ESMはデフォルトでdeferが効き、strictモードで実行され、別オリジンへはCORS制約が掛かるなど、より厳格な実行モデルを採用しています。また、import maps仕様によりベアモジュール名(import _ from 'lodash')もブラウザで解決できるようになりつつあります。
Node.jsでは2017年頃から実験的なESM対応が始まり、2020年のNode.js 14でついに安定機能になりました。拡張子.mjsか、package.jsonのtype: 'module'指定でESMとして扱われます。ただし既存のCommonJSコードベースとの相互運用や、__dirnameのような変数が存在しないなど、移行には実務的な注意点がいくつかあり、Node.jsエコシステム全体のESM化はいまだ進行中の課題です。
ESMが当たり前になる時代の設計

新しく書くJavaScript/TypeScriptコードでは、特別な事情がない限りESMを選ぶのが現代の常識になりました。TypeScriptもESMを第一級にサポートしており、Top-level awaitやdynamic import()といった機能が標準仕様として整っています。フロントエンドのバンドラはもちろん、Node.jsの新規プロジェクトもESM前提が増えました。
とはいえ、世界中のnpmパッケージの中にはCommonJSのまま長年メンテされてきたものも多数あり、完全な移行には時間がかかります。両方の形式を提供するdual packageや、ESMラッパー、実行時の動的requireなど、過渡期ならではの工夫が今後数年は必要でしょう。ESMを「次の世代」ではなく「現在の標準」として捉え、その特性を踏まえた設計を行うことが、長期的な保守性を高めます。
まとめ
ES ModulesはECMAScript 2015で標準化されたJavaScript公式のモジュール仕様で、import/exportによる静的依存解析、ライブバインディング、Tree Shaking前提の最適化など、現代的なJavaScript開発の土台となっています。ブラウザとNode.jsの両方でネイティブ実装が整い、CommonJSからの移行は進行中ですが、新規プロジェクトはESMを基本に設計するのが今や定石です。
※本記事はIT用語辞典の手書きドラフトです。公開前に最新情報・出典を確認のうえ加筆修正してください。

コメント