Edited at

JavaScriptのモジュールシステムに関するまとめ

More than 3 years have passed since last update.

普段はRailsのサブセットとしてのJavaScript(CoffeeScript)しか書いておらず、この手の話は浅学のため、ご指摘などコメントいただけると幸いです :bow:


1. 予備知識


Prototype

既存のオブジェクトを拡張することで機能を提供するライブラリ。

例えばArrayString、またグローバルな名前空間のうち、ClassHashといった汎用性のある名前を利用している。

このため名前の衝突が生じやすいという問題があった。


jQuery

WebブラウザのためのJavaScriptを容易に記述できるライブラリ。

実装をjQuery$)という名前空間に集約することで、Prototypeにおける衝突の問題を解決している。


大規模アプリケーション開発

JavaScriptにおける大規模なアプリケーション開発の場合、実装をMV*に分割する必要性が生じる。

この分割を進めると、モジュール間の依存関係が生まれる。

しかし、JavaScript単体にはこれを解決するモジュールシステムは存在しなかった。

このための解決策として、後述するCommonJSが登場する。


2. モジュールシステムのためのAPI仕様


CommonJS

JavaScriptでサーバサイドを開発するために生まれた標準APIの仕様。

元々ServerJSという名前だったが、後にその他の分野にも適用可能なものになりCommonJSに改めた。

CommonJSにはファイル操作など様々なAPIの仕様が策定されているが、その中でモジュールに関するものもある。

moduleexportsでモジュールを定義し、requireで読み込みこれを利用する」といった、現在主流になっている仕様を策定している。


AMD

Asynchronous Module Definitionの名のとおり、モジュールの非同期定義に関するAPI仕様。

当初CommonJSはブラウザ環境を考慮していなかったが、AMDはこれを考慮し、遅延読み込みに対応した。

元々はCommonJSで策定が進められていたが、後に切り離された。


API仕様の各実装


Node.jsのrequire

CommonJSのモジュールAPIの仕様に従った実装(だった)。

現在はCommonJSの仕様の枠を超え、Node.js独自の実装も行なわれている。

CommonJSの仕様を広めるきっかけになる。


Browserify

CommonJSのモジュールAPIの仕様に従って書かれたJavaScriptを、ブラウザ上で動作可能にしたモジュールシステム。

requireに指定されたモジュールを、読み込むのではなく事前にビルドすることで問題を解決する。

またこの際、依存関係も同時に解決する。


RequireJS

AMDのモジュールAPIの仕様に従った実装。

依存関係の解決は、Browserifyと異なり、ビルド時ではなく実行時に行なう。


WebPack

RequireJSやBrowserifyよりも後発のモジュールシステム。

ビルドプロセスで依存関係を解決するが、CommonJSとAMDの両方のスタイルをサポートする。

JavaScriptだけでなく、スタイルシートや画像などのアセット全般を扱うことができ、またさまざまなオプションも設定できる。


ES6のモジュール

ES6ではモジュールシステムに関する仕様が策定されている。

CommonJSの仕様に近く、exportでモジュールを定義し、importで読み込む。

JavaScriptの標準仕様となることから、将来的にES6のモジュールに置き換わることが予想される。


3. モジュールに関する現状の実装指針

ES6のモジュールシステムを見据えつつ、BrowserifyかWebPackで目的に合った方を採用すればよい。


4. 備考


パッケージ管理システム


npm

Node Package Managerの名のとおり、Node.jsにおけるパッケージ管理ツール。

Rubyでいうところのgem

Node.jsはブラウザに依存しないプラットフォームであるため、npmで公開されているパッケージもこれに準じている(ものが多い)。

ただし、npmは公式にフロントエンドのパッケージも登録することを呼びかけており、後述するbowerの利用は衰退するものと思われる。


bower

ブラウザ環境のためのパッケージ管理ツール。

Node.jsにおけるnpmの、ブラウザ環境バージョンのようなもの。

npmパッケージのひとつで、Twitterが開発。