CommonJS と ES Module の違い
- 1347単語
- 7分
- 09 Sep, 2024
JavaScript 開発において、モジュール化システムは重要な役割を果たしており、コードの管理と整理に役立ちます。CommonJS と ES Module は主要なモジュール化標準であり、モジュールの読み込み、エクスポートメカニズム、互換性などに顕著な違いがあります。この記事では、これらのモジュールシステムの主な特徴と違いを詳細に比較します。
1. モジュールの読み込み方法
CommonJS:
-
同期読み込み:CommonJS は同期的にモジュールを読み込みます。つまり、
require()
関数を使用すると、モジュールが即座に読み込まれて実行されます。この方法はサーバーサイド(例えば Node.js)には適していますが、ブラウザ環境ではパフォーマンスの問題を引き起こす可能性があります。ブラウザはモジュールの読み込みが完了するまで後続のコードを実行できません。1// モジュールのインポート2const math = require("./math");3console.log(math.add(2, 3));
ES Module:
-
静的および非同期読み込み:ES Module は静的および非同期の読み込みをサポートしています。モジュールのインポートはコンパイル時に静的に解析され、これにより JavaScript エンジンが最適化を行うことができます。ES Module は
import
構文を使用して非同期読み込み(動的import()
を使用)もサポートし、ブラウザ環境では特に重要です。1// 静的インポート2import { add } from "./math.js";3console.log(add(2, 3));45// 動的インポート6import("./math.js").then((module) => {7console.log(module.add(2, 3));8});
2. モジュールのエクスポートとインポート
CommonJS:
-
モジュールのエクスポート:
module.exports
またはexports
オブジェクトを使用して、モジュールの機能をエクスポートします。オブジェクト、関数、または他の値をエクスポートできます。1// モジュールのエクスポート2module.exports = {3add: function (a, b) {4return a + b;5},6}; -
モジュールのインポート:
require()
関数を使用してモジュールをインポートします。1// モジュールのインポート2const math = require("./math");3console.log(math.add(2, 3));
ES Module:
-
モジュールのエクスポート:
export
キーワードを使用して、モジュールの機能をエクスポートします。名前付きエクスポートとデフォルトエクスポートがサポートされています。1// 名前付きエクスポート2export function add(a, b) {3return a + b;4}56// デフォルトエクスポート7export default function add(a, b) {8return a + b;9} -
モジュールのインポート:
import
キーワードを使用してモジュールをインポートします。モジュールの一部または全体をインポートすることができます。1// 名前付きエクスポートのインポート2import { add } from "./math.js";3console.log(add(2, 3));45// デフォルトエクスポートのインポート6import add from "./math.js";7console.log(add(2, 3));
3. モジュールの解決
CommonJS:
-
動的解決:モジュールのパスは動的に解決され、コードの実行時にモジュールのパスを計算することができます。これにより、条件付きインポートや動的なモジュール読み込みが可能になります。
1const math = require("./math-" + someCondition + ".js");
ES Module:
-
静的解決:モジュールのパスはコンパイル時に静的に解決され、コンパイラはコードの実行前に依存関係を確定することができます。これにより、静的解析と最適化が可能になりますが、動的なパス解決はサポートされていません。
1import { add } from "./math.js";
4. 互換性
CommonJS:
- 主に Node.js で使用:CommonJS は Node.js のデフォルトモジュールシステムであり、ブラウザ環境では直接サポートされていませんが、Browserify や Webpack などのツールを使って CommonJS モジュールを使用することができます。
ES Module:
- 標準化:ES Module は ECMAScript 標準の一部であり、現代のブラウザと Node.js で広くサポートされています。フロントエンドとバックエンドの両方で推奨されるモジュールシステムです。
5. 実行時の挙動
CommonJS:
- 動的読み込みとキャッシュ:CommonJS モジュールは、最初の
require
の際に読み込まれて実行され、その後キャッシュされます。同じモジュールへの後続のrequire
呼び出しはキャッシュ内のモジュールインスタンスを返します。
ES Module:
- 静的読み込みと循環依存:ES Module は静的解析をサポートし、モジュールの依存関係をコンパイル時に確定することができます。循環依存には対応しており、モジュールが読み込まれる際に他のモジュールの一部内容を参照することができます。
6. エクスポート値 vs. エクスポート参照
CommonJS:
-
エクスポート値はコピー:CommonJS では、モジュールのエクスポート値はエクスポートオブジェクトのコピーです。エクスポートオブジェクトを変更しても、他のモジュールで見える値には影響しません。
math.js 1let count = 0;23module.exports = {4add: function (a, b) {5return a + b;6},7getCount: function () {8return count;9},10};1112// app.js13const math = require("./math");14console.log(math.getCount()); // 出力: 015math.count = 10; // math.getCount() の戻り値は変わらない16console.log(math.getCount()); // 依然として: 0
ES Module:
-
エクスポート値は参照:ES Module では、モジュールのエクスポート値は元のオブジェクトの参照です。エクスポートオブジェクトを変更すると、他のモジュールにも反映されます。
math.js 1export let count = 0;23export function add(a, b) {4return a + b;5}67// app.js8import { count, add } from "./math.js";9console.log(count); // 出力: 010count = 10; // math.js の count が変わる11import { count as newCount } from "./math.js";12console.log(newCount); // 依然として: 10
結論
- CommonJS はサーバーサイド(Node.js)に適しており、モジュールは同期的にロードされ、簡単に使用できますが、ブラウザ環境では追加のツールが必要です。
- ES Module は ECMAScript の標準モジュールシステムであり、静的解析と最適化をサポートし、現代のブラウザと Node.js に適しており、パフォーマンスと柔軟性が向上しています。
適切なモジュールシステムを選択することで、コードの保守性とパフォーマンスを向上させることができ、プロジェクトの要件と環境に応じた選択が重要です。