CommonJS と ES Modules の違いとは?互換性や require() と import文 の違いについて

NodeESModules

こんにちはフロントエンドエンジニアのまさにょんです!

今回は、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>

この方法だと扱いづらい点があります。

  1. HTMLファイルと密結合となる
  2. JSファイル単独で管理できない
  3. 読み込みの順番を気にしなければならない

これを解決するための手段として、さまざまなアプローチが登場しました。

その有名な解決アプローチの技術の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 の意味や特徴などをまとめると、次のとおり。

  1. ES Modules が登場する以前の Node ( ServerSide の JS )独自の Module Systemも含む仕様群。
  2. Node.jsが Defaultで採用している。
  3. ES Modulesで書かれた Module は使用できない ( CommonJS => ES Modules の互換性なし )

ES Modules

ES Modules の意味や特徴などをまとめると、次のとおり。

  1. ES2015で策定されたJSファイルから別のJSファイルを読み込む仕組み ( Module System )
  2. Web ブラウザが、Defaultで採用している Module System
  3. Node.jsも最近のバージョンで対応している。
  4. CommonJSで書かれたモジュールも使用できる ( ES Modules => CommonJS の互換性あり )
  5. ES Modules に統一していくために、動いている最中。

JavaScript書籍 Ver. 中級-上級者向け

JavaScript書籍 Ver. 初級者向け

Twitterやってます!Follow Me!

神聖グンマー帝国の逆襲🔥

神聖グンマー帝国の科学は、世界一ぃぃぃぃぃぃ!!!!!

参考・引用

  1. CommonJSとES Modulesについてまとめる
  2. TypeScriptのESMでハマる
  3. ES Modulesとは
  4. ES Modules入門 JavaScriptでモジュールを使う時代
  5. ES modules基礎知識 第1回 仕様の概要とその周辺課題
  6. TypeScript 4.7 と Native Node.js ESM

最近の投稿