こんにちはフロントエンドエンジニアのまさにょんです!
今回は、CommonJS と ES Modules の違いと、その互換性や require() と import文 の違いについて解説していきます。
目次
CommonJS と ES Modules の違いは?
JavaScript使い・FrontEndエンジニアにとって、切っても切り離せない Node の Package (Module) たち、
そんな Node の Package (Module) を取り扱うための Module System には、主に CommonJS と ES Modules の2種類があります。
ここでは、JS の Module 読み込み ( Module System ) の歴史的な経緯と、 Module System である CommonJS と ES Modules の違いについて説明していきます。
原初の HTML + JS には、モジュールの仕組み( Module System )がなかった
そもそも、原初の JavaScriptには、他のJSファイルを取り込む標準的な仕様( Module System )が、存在しませんでした。
なので、外部JSファイルを読み込みたい時は、HTMLファイルにscript
タグを書き込むことで別ファイルを読み込むようにしていました。
たとえば次のような HTMLコードです。
<script src="js/vender/jquery.min.js"></script>
<script src="js/vender/jquery.cookie.js"></script>
<script src="js/vender/jquery.easing.1.3.js"></script>
<script src="js/common.js"></script>
<script src="js/utils.js"></script>
<script src="js/app.js"></script>
この方法だと扱いづらい点があります。
- HTMLファイルと密結合となる
- JSファイル単独で管理できない
- 読み込みの順番を気にしなければならない
これを解決するための手段として、さまざまなアプローチが登場しました。
その有名な解決アプローチの技術の1つが CommonJS になります。
ただ、CommonJS は独自仕様だったため、これからはES Modulesが標準仕様として取って代わっていくと考えられ、実際に ES Modules に統一するような動きがあります。
CommonJS とは?
CommonJSとは、ServerSide などの Webブラウザ環境( ClientSide )外におけるJavaScriptの各種仕様を定めることを目標としたプロジェクトです。
そして、Node.jsはデフォルトですべてのモジュールをCommonJSで扱うようになっていました。
ただ、最近のバージョンでES Modulesに対応するなどしていて、潮流はES Modulesに流れつつあります。
CommonJSでは、外部から Module を呼び出す際はrequire()
を使用して呼び出します。
const functions = require('./libs/functions')
functions.hoge()
ES Modules とは?
ES Modules ( ECMA Script Modules ) とは、ES2015で策定された JavaScriptの Module System の規格です。
また、Module Systemとは、ファイルを外部から Moduleとして読み込み使用するための仕組みになります。
例えば、JSファイルから別のJSファイルを読み込み Moduleとして使用する場合などがそれにあたります。
Reactや、Vueなどで最近の JavaScriptフレームワーク・ライブラリを使用していると、
import
文やexport
文などを使用しますが、そういった Module利用のための新しい Module System (仕組み)が ES Modules です。
ES Modulesの一部であるimport
文とexport
文の事例を見てみます。
export
文では、次のようにModule(ファイル) から、Dataを exportするように設定することができます。
// モジュール内でのエクスポート
export const variable = 123;
export function greet(name) {
return `Hello, ${name}!`;
}
また、import
文では、他の Moduleから利用したい Data を指定します。
// モジュールからのインポート
import { variable, greet } from './example.js';
console.log(variable); // 123
console.log(greet('Alice')); // Hello, Alice!
上記の Sampleのように、ES Modules が実装されている環境では、import文を利用することで、他のJSファイルの内容を読み込むことが可能になりました。
また、ES Modules が Webブラウザだけではなく、Node.js ( ServerSide の JS実行環境 ) にも対応した Module System となったことで、
最近では、ES Modules に統一するような動きも強くなっています。
Node 環境に ES Modules に Module System を変える方法
まだ Node.js の古いバージョンなどは、Defaultですべての Module を CommonJS で扱うので、
次のような 3つの対応のいずれかで Module System を変える必要があるようです。
package.jsonを追加して"type": "module"
を設定する。main
を設定する必要がある。
{
"type": "module",
"main": "./main.js"
}
--input-type=module
をつけて実行する
node main.js --input-type=module
.mjs
に拡張子を変える。
const functions = require('./libs/functions.mjs')
functions.hoge()
CommonJS と ES Modules の互換性について
開発の際に気になるのは、CommonJS と ES Modules の互換性は、どのような状況なのかという点です。
これまで、Webブラウザでは、Module System がなく、Node.jsは独自のCommonJS で、Moduleの読み込み・利用の対応をしてきました。
しかし、Node.jsと Webブラウザ両方に対応した Module System仕様 である ES Modulesのおかげで、
Webブラウザ( ClientSide )と Node ( ServerSide )で、同様の Module規格が使用できるようになりました。
なので、CommonJS の Module から ES Modules を呼ぶのは、互換性がないため、Errorになりますが、
ES Modules から CommonJS の Module を呼ぶのは、互換性があるため実行できます。
つまり、require()
で ES Modules を使用することはできませんが、import
で CommonJS の Module を使用することはできるわけです。
CommonJS と ES Modules の違い・まとめ
Module のインポートで2つを比較すると次のような形になります。
// ESM (ES Modules)
import { robotama } from "robotama";
// CommonJS
const { robotama } = require("robotama");
CommonJS
CommonJS の意味や特徴などをまとめると、次のとおり。
- ES Modules が登場する以前の Node ( ServerSide の JS )独自の Module Systemも含む仕様群。
- Node.jsが Defaultで採用している。
- ES Modulesで書かれた Module は使用できない ( CommonJS => ES Modules の互換性なし )
ES Modules
ES Modules の意味や特徴などをまとめると、次のとおり。
- ES2015で策定されたJSファイルから別のJSファイルを読み込む仕組み ( Module System )
- Web ブラウザが、Defaultで採用している Module System
- Node.jsも最近のバージョンで対応している。
- CommonJSで書かれたモジュールも使用できる ( ES Modules => CommonJS の互換性あり )
- ES Modules に統一していくために、動いている最中。
JavaScript書籍 Ver. 中級-上級者向け
JavaScript書籍 Ver. 初級者向け
Twitterやってます!Follow Me!
神聖グンマー帝国の逆襲🔥
神聖グンマー帝国の科学は、世界一ぃぃぃぃぃぃ!!!!!
参考・引用
- CommonJSとES Modulesについてまとめる
- TypeScriptのESMでハマる
- ES Modulesとは
- ES Modules入門 JavaScriptでモジュールを使う時代
- ES modules基礎知識 第1回 仕様の概要とその周辺課題
- TypeScript 4.7 と Native Node.js ESM