JavaScriptにおけるモジュールとは、コードをファイル単位などで分割し、必要な部分をインポート(import)・エクスポート(export)できる仕組みです。ES6ではES Modules
(ESM)と呼ばれる標準モジュールシステムが導入され、import/export文が使えるようになりました。それ以前から、Node.jsではrequire関数とmodule.exportsを使うCommonJSと呼ばれるモジュールシステムが使われており、現在も双方が存在しています。
ES
Modulesではimport/export構文によりモジュール間で関数や変数をやり取りします。一方、CommonJSではrequire()でモジュールを読み込み、module.exportsで外部に公開します。技術的な違いとして、CommonJSはモジュールを同期的にロードしますが、ESMでは基本的に非同期にモジュールを読み込みます。またブラウザではESMがネイティブにサポートされているのに対し、CommonJSモジュールをそのまま読み込むことはできず、Webpackなどのバンドラを使って束ねる必要があります。
Node.js環境でも近年はESMがサポートされており、.mjs拡張子やpackage.jsonに"type": "module"を指定することでimport/exportが使えます。新規プロジェクトではES
Modulesの使用が推奨されており、既存のCommonJSとの相互運用も可能ですが、モジュールの種類を混在させる際には注意が必要です。
まずES
Modulesの例として、モジュールを二つ用意し、一方で変数や関数をexportし、他方でimportして利用します(ブラウザ環境で実行する場合、<script type="module">タグ内で動作します)。
/*** utils.js - モジュールファイル ***/
export const pi = 3.14159;
export function circleArea(radius) {
return pi * radius * radius;
}
/*** main.js - エントリポイント ***/
import { pi, circleArea } from "./utils.js";
console.log(pi); // 3.14159
console.log(circleArea(5)); // 78.53975
// デフォルトエクスポートの例
// utils.js 側で: export default function greet() { ... }
// main.js 側で: import greet from "./utils.js";
次に、Node.jsで従来使われていたCommonJSの書き方の例を示します。requireとmodule.exportsを用いて同様の機能を実現しています。
/*** utils.cjs ***/
const pi = 3.14159;
function circleArea(radius) {
return pi * radius * radius;
}
// 複数の値をモジュールの外に公開
module.exports = { pi, circleArea };
/*** main.cjs ***/
const { pi, circleArea } = require("./utils.cjs");
console.log(pi); // 3.14159
console.log(circleArea(5)); // 78.53975
解説: ES
Modules形式では、utils.jsでexportされた定数piや関数circleAreaを、main.js側でimportによって読み込んで使用しています。このとき、読み込む側ではimport { 名前 }で対応する名前を指定します。デフォルトエクスポートを使った場合(例ではコメントで記載)、import 任意の名前 from "..."という書式で読み込みます。ES
Modulesではこれらimport文はファイル先頭で静的に記述され、モジュールを非同期にロードします。
CommonJS形式では、utils.cjs側でmodule.exports = { pi, circleArea };とまとめてエクスポートし、main.cjs側でrequire("./utils.cjs")により同期的にモジュールをロードしています。CommonJSのrequireは関数呼び出しなので任意の場所で実行できる一方、ES
Modulesのimportはファイルロード時に行われる点が異なります。また、上記の例では拡張子.cjsを使用していますが、Node.jsでESMを使う場合には.mjs拡張子にするか、package.jsonでモジュールタイプを指定する必要があります。
まとめると、
import/exportを使用。モジュールは非同期ロード。ブラウザとNode.js(設定有)で使用可能。新規プロジェクトで推奨。require/module.exportsを使用。モジュールは同期ロード。Node.jsでデフォルト使用。ブラウザでは直接使用不可(バンドラが必要)。
現在では多くの場合ES Modulesを使う方向に統一されつつありますが、Node.jsの既存環境や一部ツールではCommonJSが根強く残っています。両者の違いを理解しつつ、必要に応じて変換や互換性設定を行うことで、モダンなモジュール構成で開発を進めることができます。