モジュールシステム完全解説!「CommonJS」と「 ECMAScript」 とは?【JavaScript・Node.js】

記事サムネイル

JavaScriptは、規模の小さなスクリプトから大規模なアプリケーションまで対応する言語ですが、プロジェクトが大きくなるにつれてコードの分割や管理が必要になります。
その際に重要なのがモジュールシステムです。
この記事では、JavaScriptの2つの主要なモジュールシステム、CommonJSES Modules(ESM) について、それぞれの違いや使い分け方を解説します。

この記事のポイント

モジュールとは?

モジュールとは、コードを小さく分割して再利用可能な単位として管理する仕様のことです。これにより、コードの保守性再利用性が向上します。

モジュールの仕様の中で古いものが、 CommonJS(CJS)です。
その後、ECMAScript Modules(ESM)などのいくつかの仕様が次々登場したため、分かりづらくなっています。
CJSとESM以外にも実はあるのですが、初心者にはややこしくなるので省略します。
このように、モジュールの仕様は複数存在し、そのプログラムがどの仕様に則って書かれているかを解釈するのは読み込み側の責務となります。

モジュールシステムを使うと、以下のようなことができます。

  • 外部ライブラリやファイルの機能をインポートして利用する。
  • 自分で作成した関数や変数を他のファイルにエクスポートする。

CommonJSとは?

CommonJS は、Node.jsで使用されるモジュールシステムで、JavaScriptのサーバーサイド開発を支える主要な仕組みです。
require と module.exports の記述を使ってモジュールを管理します。

古いNode.jsのライブラリなどはこちらの仕様に沿った記述で書かれていることが多いです。

特徴

  • 同期的にモジュールを読み込む仕組み。
  • 主にNode.js環境で使用される。
  • 既存のコードベースで広く採用されている。
  • 古めの仕様

書き方

モジュールのエクスポート

// utils.js
function add(a, b) {
  return a + b;
}

module.exports = add;

モジュールのインポート

// main.js
const add = require('./utils'); //ファイルのパスを書き、エクスポートした通りの名前でインポートして使用

console.log(add(2, 3)); // 5

メリット

  • シンプルな構文で、Node.jsのエコシステムで広く使われている。
  • 動的にモジュールを読み込むことが可能。

デメリット

  • 同期的な読み込みのため、ブラウザ環境には不向き。
  • 古いシステムであるため、最新のJavaScript仕様と整合性がない場合がある。

ES Modules(ESM)とは?

ES Modules は、JavaScriptの標準モジュールシステムで、importと export の記法を使ってモジュールを管理します。
ES6(2015年)で導入され、現在はブラウザやNode.jsの最新バージョンでサポートされています。

特徴

  • 非同期でモジュールを読み込む仕組み。
  • クライアントサイド(ブラウザ)とサーバーサイド(Node.js)で利用可能。
  • 静的構造解析が可能なため、ツールが最適化しやすい。
  • 2015年に導入された比較的新しい仕様

書き方

モジュールのエクスポート (2種の方法)

// utils.js

// namedエクスポート(名前付きエクスポート)方法
export function add(a, b) {
  return a + b;
}
export const PI = 3.14159;


// defaultエクスポート方法
export default function subtract(a, b) {
  return a - b;
}

モジュールのインポート (2種の方法)

// main.js

// namedインポート(名前付きインポート)方法
import { add, PI } from './utils';

console.log(add(2, 3)); // 5
console.log(PI);        // 3.14159


// defaultインポート方法
import subtract from './utils';
console.log(subtract(5, 2)); // 3

メリット

  • ブラウザでネイティブサポートされており、トランスパイルが不要である。(そのまま動く)
  • 静的解析により、デッドコードの削除(ツリーシェイキング)が可能。

デメリット

  • 一部の古い環境では利用できない。
  • CommonJSとの互換性が完全ではない。

CommonJSとES Modulesの違いまとめ

CommonJS (require) ES Modules (import/export)
使用環境 Node.js環境(サーバーサイド) ブラウザとNode.js(Node,jsは最新環境)
読み込み方式 同期的(実行時にモジュールをロード) 非同期的(事前に解析可能)
構文の特徴 require, module.exports import, export
動的インポート 可能 部分的に可能(import() 関数で対応)
静的解析 不可能 可能(ツリーシェイキングが可能)
ブラウザ対応 非対応 対応

CommonJSとES Modulesの使い分け

CommonJSを使うべき場面

  • Node.jsを使ったサーバーサイドアプリケーションの既存プロジェクト。
  • 同期的なモジュール読み込みが問題にならない場面。

ES Modulesを使うべき場面

  • モダンなJavaScript環境(ブラウザや最新のNode.js)での開発。
  • ツリーシェイキングや静的解析を活用した効率的なバンドルが必要な場面。
  • フロントエンド開発(特にモジュールバンドラーを使う場合)。

実際のプロジェクトでの例

Node.jsでESModulesを使う

Node.jsでもimport/exportを使用できますが、
デフォルトで全てのモジュールをCommonJSで扱うので、以下のいずれかの設定が必要です。

必要な設定(どれか1つ)

  1. ファイル拡張子を .jsではなく.mjs にする。
  2. package.json"type": "module" を追加。
  3. ESMを標準サポートしていない古いNode.jsのバージョンでは、ファイル実行コマンド時に--input-type=module オプションをつける

1の記述例

// utils.mjs
export function multiply(a, b) {
  return a * b;
}

// main.mjs
import { multiply } from './utils.mjs';

console.log(multiply(3, 4)); // 12

2の記述例

// package.json
{
  "type": "module"
}

3の記述例

node main.js --input-type=module

補足

CommonJSからESMを呼ぶことはできませんが、ESMからCommonJSを呼ぶことはできます。
理由として、CommonJSでは require を使用しますが、ESM(export/import)のモジュールは非同期的に動作するため、require ではESMを直接読み込むことができません。

発展:named (名前付き)インポート/エクスポートdefault(デフォルト)インポート/エクスポートの違い

難しい場合は、飛ばしてもOKです。

1. namedインポートとエクスポート

  • namedエクスポート:複数の関数や変数を個別にエクスポートできる。
  • namedインポート:名前を指定してエクスポートされた項目をインポートする。

utils.js

// 複数の関数や変数をエクスポート
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;
export const PI = 3.14159;

main.js

// 名前を指定して個別にインポート
import { add, subtract, PI } from './utils.js';

console.log(add(5, 3));       // 8
console.log(subtract(5, 3));  // 2
console.log(PI);              // 3.14159

注意

  • インポート時の名前は、エクスポート時の名前と一致している必要がある。
  • エイリアス(別名)を指定することも可能。

エイリアス(as)を使った例

import { add as addition } from './utils.js'; //このファイル内ではadd関数をadditionという名前で使用可能

console.log(addition(2, 3)); // 5

2.デフォルトインポートとエクスポート

  • デフォルトエクスポート:1つのモジュールで1つの項目のみをエクスポート。
  • デフォルトインポート:インポート時に自由な名前を指定可能。

utils.js

// デフォルトエクスポート
export default function multiply(a, b) {
  return a * b;
}

main.js

// デフォルトインポート(好きな名前でインポート可能)
import multiply from './utils.js';

console.log(multiply(5, 3)); // 15

注意

  • デフォルトエクスポートは1つのモジュールにつき1回のみ可能。
  • インポート時に名前を自由に変更できるため、モジュールの設計に柔軟性がある。

まとめ

  • CommonJS はNode.jsの標準モジュールシステムで、シンプルな構文を持ち、サーバーサイドで広く使われています。
  • ES Modules(ESM) はモダンJavaScriptの標準で、非同期的で効率的なモジュール管理が可能です。
  • 使い分けのポイントは、既存のプロジェクトや互換性を重視する場合はCommonJSを、モダンな環境やフロントエンドではES Modulesを選ぶと良いでしょう。
    基本的にこれからは、ESModulesが主流になっていきます。

どちらもJavaScript開発において欠かせない技術なので、特徴と用途を理解して適切に使い分けましょう!

CodeVilageでは無料カウンセリングを実施しております!

まずはお気軽に無料カウンセリングへご参加ください!
「興味はあるけど、自分にできるか不安...」
「どんなキャリアを描けばいいのか分からない...」
そんなあなたのために!!
何でも相談できる無料カウンセリングを実施しています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です