1. モジュールシステムとは何か
モジュールシステムは、コードを複数のファイルに分割し、それらの間で機能を共有する仕組みです。これにより、大規模なアプリケーションを管理しやすくなります。
JavaScriptには主に2つのモジュールシステムがあります:
- CommonJS: Node.js環境で使用される古い仕組み
- ESModule: ES2015で標準化された新しい仕組み
2. CommonJSの基本構造
エクスポート(関数を外部に公開)
// mathUtils.js (CommonJS)
function add(a, b) {
return a + b;
}
function multiply(a, b) {
return a * b;
}
//以下3つの記述を同時に各ことはない(それぞれ独立していると思って読んでください)
// 方法1: 個別にエクスポート
exports.add = add;
exports.multiply = multiply;
//------------
// 方法2: オブジェクト形式でエクスポート
module.exports = {
add: add,
multiply: multiply
};
//------------
// 方法3: オブジェクトのプロパティとしてではなく、関数そのものをエクスポート(CommonJSにはデフォルトエクスポートという概念はなく、ただエクスポートしてるだけ)
module.exports = add;
インポート(関数を他のファイルから読み込み)
// main.js (CommonJS)
// 方法1: 全体をインポート
const math = require('./mathUtils');
console.log(math.add(2, 3)); // 5
// 方法2: 分割代入でインポート
const { add, multiply } = require('./mathUtils');
console.log(add(2, 3)); // 5
// 方法3: 関数を直接取得
const add = require('./mathUtils'); // 関数そのものを取得
console.log(add(2, 3)); // 5
3. ESModuleの基本構造
エクスポート(関数を外部に公開)
// mathUtils.js (ESModule)
// 方法1: 関数定義と同時にエクスポート
export function add(a, b) {
return a + b;
}
export function multiply(a, b) {
return a * b;
}
// 方法2: 後からまとめてエクスポート
function subtract(a, b) {
return a - b;
}
function divide(a, b) {
return a / b;
}
export { subtract, divide };
// 方法3: デフォルトエクスポート
export default function calculate(a, b, operation) {
// 計算処理
}
//----まはた----
const calculate = (a, b, operation) => {
// 計算処理
}
export default calculate
インポート(関数を他のファイルから読み込み)
// main.js (ESModule)
// 方法1: 名前付きインポート({}が必要で、エクスポートした名前を同じ名前にする)
import { add, multiply } from './mathUtils.js';
console.log(add(2, 3)); // 5
//---まはた、エイリアス付きインポート(名前付きエクスポート関数に別名を付けられる)
import { add as add_alias, multiply as multiply_alias } from './mathUtils.js';
console.log(add_alias(2, 3)); // 5
// 方法2: デフォルトインポート({}が不要)
import calculate from './mathUtils.js';
console.log(calculate(2, 3, 'add'));
//---まはた、デフォルトエクスポートの場合はas無しでも別名を付けられる
import differentName from './mathUtils.js';
console.log(differentName(2, 3, 'add'));
// 方法3: 両方を組み合わせ
import calculate, { add, multiply } from './mathUtils.js';
// 方法4: 全体をインポート
import * as math from './mathUtils.js';
console.log(math.add(2, 3)); // 5
4. 関数の呼び出し方の違い
CommonJS
// mathUtils.js
exports.add = function(a, b) {
return a + b;
};
// main.js
const math = require('./mathUtils');
math.add(2, 3); // オブジェクトのプロパティとして呼び出し
// または
const { add } = require('./mathUtils');
add(2, 3); // 直接関数を呼び出し
ESModule
// mathUtils.js
export function add(a, b) {
return a + b;
}
// main.js
import { add } from './mathUtils.js';
add(2, 3); // インポートした関数を直接呼び出し
// または
import * as math from './mathUtils.js';
math.add(2, 3); // 名前空間経由で呼び出し
5. 重要な違いのまとめ
構文の違い
項目 | CommonJS | ESModule |
---|---|---|
インポート | require() |
import |
エクスポート |
module.exports / exports
|
export / export default
|
ファイル拡張子 | .js |
.js または .mjs
|
実行タイミングの違い
CommonJSは実行時にモジュールを読み込みます:
// 条件付きでrequire可能
if (someCondition) {
const module = require('./optional-module');
}
ESModuleはコンパイル時にモジュールを読み込みます:
// 条件付きimportは基本的に不可能
import { something } from './module.js'; // 常にファイルの最上位で実行される
環境での使用
- CommonJS: Node.js環境で標準
- ESModule: ブラウザとNode.js両方で使用可能(Node.jsでは比較的新しい)
6. 実際の使用場面での違い
プロジェクト設定
CommonJS: package.jsonで特別な設定は不要
{
"name": "my-project"
}
ESModule: package.jsonで明示的に指定が必要
{
"name": "my-project",
"type": "module"
}
TypeScriptでの使用
// CommonJS形式
const math = require('./mathUtils'); // TypeScript側でtype情報が制限される
// ESModule形式
import { add } from './mathUtils.js'; // TypeScript側で完全なtype情報が利用可能
この基本的な違いを理解することで、プロジェクトでどちらのモジュールシステムを使用するかを適切に判断できるようになります。現在のWebエンジニアリングでは、ESModuleが主流になっています。