JavaScriptの依存関係を処理するバンドラとしてWebpackやRollupなど、いくつかのものが存在しています。今回は、この2つを比較してみました。
CommonJSとES6 Module
まず、WebpackとRollupの話に入る前に、JavaScriptに2種類存在するモジュールシステムについて説明します。
もともとブラウザ用ということもあって、JavaScriptにモジュール化の仕組みはなかったのですが、Node.jsなど他の環境でJavaScriptを使うのにあたって、「ないと困る」ということになったようなこともあり、require
とmodule.exports
を使ったモジュールシステムであるCommonJSが制定されました。
その後、JavaScript自体にもES6でimport
/ export
の仕組みが導入されましたが、両者は(変換して相互運用できなくはないのですが)別物となっています。
特に、1つのモジュールから大量のプロパティを出しているような場合、CommonJS形式では全部エクスポートするしかなかったのですが、ES6 Moduleでは使用しているモジュールが静的に判定できるので、Tree Shakingなどをやりやすくなっています。
両者の違い
ネイティブなモジュールシステム
Webpack 1ではCommonJSしか認識できず、ES6 Moduleで書かれたものはBabelなどで下処理しないと処理不能だったのですが、Webpack 2以上ではES6 Moduleも認識できるようになっています(BabelのES6 Module変換は止めておく必要があります)。
一方、RollupはES6 Moduleだけをネイティブに実装していて、CommonJSの処理にはプラグインが必要です。
ESのバージョン
Webpackの場合、Webpack 2以上ではES6も通せるはずなのですが、babel-loader
でES5に変換してから読み込むのが一般的な使用法となっています1。一方、RollupはJavaScriptとしてもES6が前提になっていて、ES5にしたい場合は出力時にBabelを通します。
この違いが目立つのは、class
や...
など、ES5に変換しようとすれば補助関数が必要になるようなコードです。モジュールごとに変換をかけるWebpackでは、同じ関数があちこちに作られてしまいます。一方、Rollupでは全体に1つで済みます。
名前空間の扱い
Webpackでは「ファイルの名前空間を、関数を使って再現する」という方針を取っています。一方で、Rollupでは「名前の衝突はリネームで解決して、フラットな空間に開く」という形になっています。
そのため、コードサイズ的にはRollupのほうが有利なのに対して、「ファイル分割」や「動的ロード」といった、モジュール間を疎結合にするような動作についてはWebpackが有利となります。
JavaScript以外の扱い
WebpackはJavaScript以外のCSSや画像に関しても活用されていますが、Rollupは基本的にJavaScriptの処理用となっています。
-
Webpackでも、出力時にUglifyES経由でES5にする、というアプローチがありそうではありますが、ローカル環境ではそうもいかなさそうですし、Babelでさらにtransformを差し込みたい場合は、またややこしいです。 ↩