ECMAScript、ES Modules、CommonJS を理解する

公開日

JavaScript あるあるなのがこんな疑問です🤔

  • ECMAScript って何? JavaScript と何が違うの?
  • ES Modules って何? CommonJS って何?
  • importrequire って何が違うの? どう使い分けるの?

この記事では、そんな疑問を解消すべく ECMAScript、CommonJS、ES Modules について解説します。 また、実行環境 (ブラウザ、Node.js)、JavaScript エンジン、レンダリングエンジンとの関係についても紹介します。

ちなみに、この辺りの知識が無くても JavaScript や React の学習は進められます。 僕も最初はこの辺りがよく分からないまま React をやっていました。 最初はなんとなく雰囲気を知るだけでも十分だと思います。

それでは見ていきましょう!

概要

まずは、それぞれの概要を見てみましょう。

名前概要
ECMAScriptJavaScript の言語仕様。
ES ModulesECMAScript の中のモジュール機能の仕様。
文法は importexport
CommonJSECMAScript とは別のモジュール機能の仕様。
文法は requiremodule.exports

3 つの関係を図にすると次のような感じになります。

以降では、それぞれの詳細を見ていきます。

ECMAScript

ECMAScript とは

ECMAScript とは、JavaScript の言語仕様です。 つまり、ECMAScript とは、JavaScript が実行される時にどのように文法が解釈されて、どのように処理されるべきかを定義したものです。 ブラウザ特有の API (DOM 操作、fetch() など) や Node.js 特有の API (fs など) は含みません。

ECMAScript はあくまで仕様 (ただの文書) であり、JavaScript を実行できるわけではありません。 JavaScript を実行するのは、ECMAScript に準拠して実装された JavaScript エンジン (V8 など) です。

どうして JavaScript は「言語」と「言語仕様」の呼び方が違うのか? これには歴史的な経緯があります。 気になる方は調べてみてくださいね。

ECMAScript のバージョン

プログラミング言語はバージョンが上がるにつれて言語仕様が増えていきます。 JavaScript の場合、ECMAScript が言語仕様なので、ECMAScript にバージョンが付きます。

ECMAScript のバージョンは次のようになっています。 当初は「1、2、...」のように連番だったものの、2015 年から毎年バージョンアップすることになり、今は「ECMAScript 2015 (ES2015)」のように年号で呼ぶことが推奨されています。

バージョン公開年特徴
ECMAScript 11997
ECMAScript 21998
ECMAScript 31999
ECMAScript 4放棄仕様を複雑にしすぎた結果、合意形成できず、放棄することに。
ECMAScript 52009
ECMAScript 5.12011
ECMAScript 2015
(ECMAScript 6)
2015 年画期的なバージョンアップ。現在の JavaScript の核となる機能が数多く追加された (クラス、モジュール、アロー関数、Promise など)。ここで追加されたモジュール機能を ES Modules と呼ぶ。
ECMAScript 20162016
ECMAScript 20242024

ES Modules

ES Modules とは

ES Modules (ECMAScript Modules) とは、ECMAScript の中で定義されたモジュール機能の仕様です。 ECMAScript 2015 で追加されました。 JavaScript 標準のモジュール機能の仕様と言えるでしょう。

Node.js はモジュール機能として CommonJS を採用していたものの、2017 年に ES Modules の試験的なサポートを開始し、2019 年に正式にサポートするようになりました。 これにより、CommonJS から ES Modules への移行が進んでいます。

ES Modules の文法

ES Modules では、次のような文法でモジュールのインポート・エクスポートを行います。

種類文法
インポートimport
エクスポートexport

CommonJS

CommonJS とは

CommonJS とは、モジュール機能の仕様です。 ECMAScript とは別になります。

正確に言えば、CommonJS にはモジュール機能以外の仕様も存在します。 しかし、モジュール機能以外はほぼ使用されていないので、「CommonJS = モジュール機能の仕様」という認識で OK です。

CommonJS は JavaScript のモジュール機能として長らく利用されてきました。 しかし、ES Modules が登場し、Node.js が ES Modules をサポートした現在では、CommonJS より ES Modules を使う方がいいでしょう。

CommonJS の歴史

  • 2000 年代
    • JavaScript の人気が増すにつれて、JavaScript をサーバーでも使用したいというニーズが大きくなりました。 しかし、ECMAScript では機能不足。
  • 2009 年
    • 【CommonJS 登場】
      サーバーサイド JavaScript の仕様を定めるために、CommonJS プロジェクトが立ち上げられました。 ECMAScript を補完する仕様が定められていきます。
    • 【Node.js 登場】
      サーバーサイドの実行環境である Node.js が登場。 ECMAScript にモジュール機能が無かったので、Node.js は CommonJS のモジュール機能を採用しました。
  • 2015 年
    • 【ES Modules 登場】
      JavaScript 標準と言えるモジュール機能が登場しました。 JavaScript に 2 種類のモジュール機能が存在するというカオスな時代に突入します。
  • 2017 年
    • Node.js が ES Modules を試験的にサポート。
  • 2019 年
    • Node.js が ES Modules を正式にサポート。 これによって、CommonJS から ES Modules への移行が進むことに。

CommonJS の文法

CommonJS では、次のような文法でモジュールのインポート・エクスポートを行います。

種類文法
インポートrequire
エクスポートmodule.exportsexports

実行環境

ECMAScript、ES Modules、CommonJS と見てきましたが、いずれも「仕様」でした。 実際には、ブラウザや Node.js といった実行環境上で JavaScript を実行します。

最後に、仕様 (ECMAScript、ES Modules、CommonJS) と、実行環境 (ブラウザ、Node.js) の関係を整理します。

ブラウザ

ブラウザ上の JavaScript では、DOM 操作や fetch() を実行します。 しかし、ブラウザ特有の機能は ECMAScript には含まれません。 ブラウザ特有の機能は「Web 標準 API」と呼ばれ、ECMAScript とは別の団体 (W3C、WHATWG) が仕様を策定しています。

つまり、ブラウザは「ECMAScript」と「Web 標準 API」を実装しているわけです。 それぞれ次のように「JavaScript エンジン」と「レンダリングエンジン」に分けて実装されています。

仕様実装
ECMAScriptJavaScript エンジンV8、JavaScriptCore、SpiderMonkey など
Web 標準 APIレンダリングエンジン、他Blink、WebKit、Gecko など

以上の関係をまとめると次のような感じです。

Node.js

Node.js 上の JavaScript では、ファイルの読み書きなどを実行します。 しかし、サーバー特有の機能は ECMAScript には含まれません。 Node.js では、サーバー特有の機能を独自の API として多数実装しています (fsprocess など)。

Node.js は ECMAScript の実装に V8 を使用しています。 V8 は Chrome で使用されている JavaScript エンジンです。

Node.js はモジュール機能として CommonJS を実装しています。

以上の関係をまとめると次のような感じです。

まとめ

ECMAScript、ES Modules、CommonJS について見てきました。

歴史的な経緯により、JavaScript には ES Modules と CommonJS という 2 つのモジュール機能の仕様が存在します。 CommonJS は JavaScript のモジュール機能として長らく使用されてきました。 しかし、2015 年にモジュール機能の標準仕様である ES Modules が登場したことで、現在は CommonJS から ES Modules への移行が進んでいるところです。

実際のプロジェクトにおいて、どちらのモジュール機能を採用するかは要件次第になってきます。 新規プロジェクトであれば、標準仕様である ES Modules の採用を推奨します。 既存プロジェクトで CommonJS が採用されている場合、段階的に ES Modules に移行していくアプローチが現実的でしょう。

この記事が JavaScript の理解の手助けになれば嬉しいです😊