JavaScript/ECMAScript Module
ECMAScript Module (ESM) とは
編集ECMAScript Module (以下、ESM) は、JavaScriptの公式なモジュールシステムであり、モダンなJavaScriptアプリケーションの構築において重要な役割を果たします。ESMは、コードをモジュール化し、再利用可能でスケーラブルな構造を提供するための標準的な方法です。
特徴
編集- 標準規格: ECMAScript (JavaScript) の公式仕様として採用。
- 静的構造: モジュールの依存関係がコード解析時に決定される。
- ツールフレンドリー: Tree Shakingや静的解析に対応。
- ブラウザネイティブサポート: 近年のブラウザやNode.jsで直接利用可能。
基本的な構文
編集モジュールのエクスポート
編集モジュールは、エクスポートを使って他のモジュールにデータや機能を提供します。
名前付きエクスポート
編集特定の名前を付けてエクスポートします。
- math.js
export const add = (a, b) => a + b; export const subtract = (a, b) => a - b;
デフォルトエクスポート
編集モジュールに1つの主要なエクスポートを持たせる場合に使用します。
- logger.js
export default function log(message) { console.log(message); }
モジュールのインポート
編集モジュールを使用するには、import
を使います。
名前付きインポート
編集import { add, subtract } from './math.js'; console.log(add(2, 3)); console.log(subtract(5, 3));
デフォルトインポート
編集import log from './logger.js'; log('Hello, ESM!');
名前の変更 (エイリアス)
編集import { add as addition } from './math.js'; console.log(addition(4, 5));
ワイルドカードインポート
編集モジュール全体を1つのオブジェクトとしてインポートします。
import * as MathUtils from './math.js'; console.log(MathUtils.add(2, 3)); console.log(MathUtils.subtract(5, 2));
ESMの実行環境
編集ブラウザ
編集ESMはモダンブラウザでネイティブにサポートされています。HTMLでモジュールを読み込む場合、<script>
要素にtype="module"
属性を追加します。
<script type="module"> import { add } from './math.js'; console.log(add(2, 3)); </script>
ESMに非対応なブラウザのためのフォールバック
編集古いブラウザがECMAScript Module(ESM)をサポートしていない場合でも、<script>
要素のnomodule
属性を活用することで、シンプルにフォールバックを提供できます。
<!-- ESMをサポートするブラウザ用 --> <script type="module" src="./app.js"></script> <!-- ESMをサポートしないブラウザ用 --> <script nomodule src="./app.cjs.js"></script>
解説
編集type="module"
: この属性を持つスクリプトは、ESMとして処理されます。ESMをサポートするブラウザのみがこれを読み込みます。nomodule
: この属性を持つスクリプトは、ESMをサポートしないブラウザでのみ実行されます。
利点
編集- 簡潔さ: 条件分岐をJavaScriptコードで書く必要がなく、HTML内で分岐を実現できます。
- 効率性: ESM対応ブラウザと非対応ブラウザの両方に適したスクリプトを簡単に提供できます。
この方法は、特にレガシーブラウザをサポートする必要がある場合に有用です。
相対パスと絶対パス
編集- 相対パス:
./module.js
または../module.js
- 絶対パス:
/path/to/module.js
または完全なURLhttps://example.com/module.js
Node.js
編集Node.jsでは、ESMはpackage.json
に"type": "module"
を追加することで有効化できます。
- package.json
{ "type": "module" }
実行例
編集- index.mjs
import { add } from './math.js'; console.log(add(1, 2));
node index.mjs
CJS (CommonJS) との違い
編集特徴 | ESM | CJS |
---|---|---|
エクスポート方法 | export / export default |
module.exports
|
インポート方法 | import |
require
|
読み込みタイミング | 静的解析 (ビルド時) | 動的解析 (実行時) |
非同期性 | インポートが非同期 (ブラウザ) | 同期的 |
CJSからESMへの移行
編集- Node.jsアプリケーションでは、ESMへの移行を考える際に
require
とimport
の違いを理解することが重要です。 - 移行時の注意点:
- ファイル拡張子を
.js
から.mjs
に変更するか、package.json
に"type": "module"
を設定する必要があります。 __dirname
や__filename
は直接使用できません。代わりに以下のように取得します:
- ファイル拡張子を
import { fileURLToPath } from 'url'; import { dirname } from 'path'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename);
実践的な活用
編集動的インポート
編集ESMでは、import()
を使った動的インポートが可能です。これにより、必要なときにモジュールを非同期で読み込むことができます。
async function loadModule() { const { add } = await import('./math.js'); console.log(add(5, 6)); } loadModule();
Tree Shaking
編集ESMの静的構造により、未使用のコードをビルド時に除去できます。これにより、最適化された軽量なバンドルが生成されます。
Web WorkersとESM
編集Web Workers内でもESMを使用できます。
- worker.js
import { add } from './math.js'; self.postMessage(add(3, 4));
- main.js
const worker = new Worker('worker.js', { type: 'module' }); worker.onmessage = (event) => { console.log(event.data); };
よくある問題と対処法
編集ファイル拡張子
編集ESMでは、import
文で拡張子を省略できません。正しい拡張子を指定してください。
// NG import { add } from './math'; // OK import { add } from './math.js';
同一ファイルでのCJSとESMの混在
編集CJSとESMを同一ファイルで混在させることはできません。必要に応じて、モジュール形式を分けるか、動的インポートを検討してください。
まとめ
編集ESMはJavaScriptの標準モジュールシステムとして、モダンな開発環境において欠かせない存在です。静的解析やブラウザネイティブのサポートにより、効率的なモジュール管理が可能になります。CJSからESMへの移行や、ツールチェーンとの統合を進めることで、よりスケーラブルでモジュール化されたアプリケーションを構築できるでしょう。