1. CJS と ESM のざっくり違い
-
CJS (CommonJS)
- Node.js が独自に採用した「昔の」モジュールシステム
-
require/module.exports
-
ESM (ECMAScript Modules)
- JavaScript 公式仕様のモジュールシステム
-
import/export
■ 文法の違い
CJS (CommonJS)
// math.cjs or math.js (CJS環境)
const PI = 3.14;
function area(r) {
return PI * r * r;
}
module.exports = {
PI,
area,
};
// main.cjs or main.js (CJS環境)
const { area } = require("./math");
console.log(area(2));
ESM (ECMAScript Modules)
// math.mjs or math.js ("type": "module" 環境)
export const PI = 3.14;
export function area(r) {
return PI * r * r;
}
// default export も可能
export default {
PI,
area,
};
// main.mjs or main.js ("type": "module" 環境)
import { area } from "./math.js";
// default なら: import math from "./math.js";
console.log(area(2));
2. Node.js における挙動の違い
package.json の type フィールド
| package.json の設定 |
.js の扱い |
主に使うモジュールシステム |
|---|---|---|
| なし | CJS | CommonJS |
"type": "commonjs" |
CJS | CommonJS |
"type": "module" |
ESM | ES Modules |
CJS モード(デフォルト / "type": "commonjs")
-
.js-> CJS 扱い -
.cjs-> CJS 扱い -
.mjs-> ESM 扱い
ESM モード("type": "module")
-
.js-> ESM 扱い -
.cjs-> CJS 扱い -
.mjs-> ESM 扱い
3. ブラウザの挙動
ブラウザは ESM が標準対応。
HTML 側で type="module" を指定すると使える。
index.html
<script type="module" src="/main.js"></script>
main.js
import { hello } from "./lib.js"; // lib.jsはこの時点で自動でfetchされるのでscriptタグで読み込む必要はない
hello();
lib.js
export function hello() {
console.log("Hello ESM in browser!");
}
※ 注意:
- 相対パスで
./lib.jsのように 拡張子必須 -
file:///直開きでは動かない場合があるので簡易サーバー推奨
4. 現在のエコシステム状況
■ ざっくりまとめ
-
新規プロジェクト → ESM 推奨
- Node.js 公式も ESM をスタンダードとして扱い始めている
- Vite / Next.js / bundler / Linter / TS も ESM 前提で進化
-
CJS はレガシー互換枠
- 既存の npm パッケージに CJS がまだ多く残っている
- 簡易スクリプト用途で
requireが未だによく使われる - ただし「新規で CJS を採用し続ける理由」はほぼなくなってきている
実務的な指針
- サーバーサイド・フロントエンド問わず 新しく書くコードは ESM を基本にしてよい
- 既存ライブラリやプロジェクトが CJS の場合のみ、互換性維持のために CJS を理解しておく程度で OK
- TypeScript + Node.js も ESM 前提設計が主流になりつつある
5. ESM のメリット / CJS が残っている理由
ESM のメリット
- JavaScript 公式仕様(ブラウザと Node で統一)
-
import/exportによる静的解析がしやすく、
bundler の最適化(tree-shaking 等)がしやすい - TS / bundler / Linter が ESM を前提に進化中
■ CJS が残っている主な理由
- Node.js 初期からの膨大な CJS パッケージ資産
- ちょっとしたスクリプトなら
"type": "module"等の設定が不要で楽 - 既存大規模プロジェクトの全面移行コストが高い
6. まとめ
-
CJS
- 文法:
require,module.exports - Node.js 独自の歴史的モジュール
- 既存資産・簡易スクリプト向け、互換目的で存続
- 文法:
-
ESM
- 文法:
import,export - JavaScript 公式標準モジュール
- ブラウザ & Node.js 共通、2026年時点の「新規標準」
- 文法:
-
実務的結論
- 新規:ESM 一択で OK
- 既存 CJS を読む・繋ぐために CJS の知識は最低限持っておく