2017年6月7日
webpackとRollup:似て非なるもの
(2017-04-07)by Rich Harris
本記事は、原著者の許諾のもとに翻訳・掲載しております。
先日、Facebookは 膨大なプルリクエスト をReactにマージして、既存のビルドシステムを Rollup ベースのシステムに移行しました。 その結果 、 何人もの人々 から「なぜwebpackではなくRollupを選んだのか」という質問が寄せられました。
これは、もっともな疑問でしょう。 webpack は、近年JavaScriptコミュニティで最も評価されているツールの1つです。毎月のダウンロード数は何百万件にもおよび、何万個ものウェブサイトやアプリケーションに使用されています。巨大なエコシステムがあり、コントリビュータも多くいます。さらにオープンソースプロジェクトとしては珍しく、 かなりの寄付金 が集まっています。
それに比べるとRollupは小規模です。しかしReact以外にも、Vue、Ember、Preact、D3、Three.js、Momentなど、数々の有名なライブラリにRollupが使われています。一体なぜでしょう。誰もが認めるJavaScriptモジュールバンドラ以外のツールも使われている理由とは、何なのでしょうか?
2つのバンドラについて
webpackは、2012年に Tobias Koppers によって公開されたツールです。このツールの目的は、既存のツールでは対処できなかった難題を解決すること、すなわち複雑なシングルページアプリケーション(SPA)の作成を可能にすることでした。webpackにおいて特に革新的だったのが、以下の2つの機能です。
-
コード分割機能 によって、アプリケーションを管理可能なチャンクに分割して、オンデマンドで読み込めるようにします。これによりユーザーは、アプリケーション全体のダウンロードとパースを待つ場合よりも、はるかに早くインタラクティブなサイトを使用できるようになります。これは手作業でも 可能ではありますが 、大変な作業になります。
-
画像やCSSなどの 静的アセット をアプリケーションにインポートして、依存性グラフ内で別ノードとして扱うことができます。ファイルを適切なフォルダに格納する作業に神経を使ったり、ファイルのURLにハッシュを追加するためにスクリプトをいじったりする必要はありません。webpackが自動で処理してくれます。
一方、Rollupが開発された背景は異なります。その目的は、優れたES2015のモジュールを活用して、一様に配布でき、できるだけ効率的なJavaScriptライブラリを作成可能にすることでした。webpackを含む他のモジュールバンドラの場合は、各モジュールを関数にラップする必要があります。また、それらをバンドルに含めるために各ブラウザに合った require
の実装をして、その1つ1つを評価しなければなりません。オンデマンドで読み込むものが必要な場合は問題ありませんが、そうでなければ無駄な作業になります。また、 モジュール数が多いほど、大変なことになります 。
ES2015のモジュールを使うと、別のアプローチが可能になります。その手法を採用しているのがRollupです。具体的には、全てのコードを同じ場所に置いて、一括で評価を行います。そのため、コードが簡潔でシンプルになり、起動速度が向上します。 実際にRollupのREPLで、確認してみてください。
一方で短所もあります。コード分割は厄介な問題を引き起こす可能性があり、Rollupの記述時にはサポートされません。また、RollupはHMR(Hot Module Replacement)に非対応です。そして、Rollupを使おうとする方々にとって最大の難点は、( プラグイン を介して)大半のCommonJSファイルを処理できるにもかかわらず、中にはES2015に変換されないものがあるという点でしょう。一方webpackの場合は、指定したものは全て問題なく処理されます。
結局、どちらを使うべきか
ここまでの説明で、用途が異なる2つのツールが共存し、補完し合っている理由を理解していただけたと思います。要点をまとめると次のようになります。
アプリケーションにはwebpackを、ライブラリにはRollupを使おう
これは厳密なルールというわけではありません。Rollupを用いて構築されているサイトやアプリケーション、そしてwebpackで作成されているライブラリはたくさんあります。ただ、上記の内容は良い目安になるでしょう。
コード分割が必要な場合や、多くの静的アセットを使用する場合、またはCommonJSへの依存性が高いものを開発している場合は、webpackを使うことをお勧めします。一方、ES2015のモジュールをコードベースとしており、他者も使用できるものを作成しているのであれば、Rollupを使うのが良いでしょう。
パッケージの作成者はpkg.moduleを使おう
長い間、JavaScriptライブラリの使用は博打のようなものでした。開発者とライブラリの作成者の間で、モジュールシステムに対する考えが一致していなければならないためです。例えば開発者がBrowserifyを使用していても、ライブラリの作成者がAMDを好む場合は、ビルド前に統合作業などが必要になります。この問題は Universal Module Definition (UMD) のような フォーマットを使用することで解決できます。しかし、全面的に適用されていないため、結果は保証されていませんでした。
この点を大きく変えたのがES2015で、言語仕様として import
と export
が含まれています。将来的には、曖昧性が排除され、よりシームレスに機能するようになるでしょう。ただ、残念ながら(大半の)ブラウザ、およびNodeでは import
と export
がまだサポートされていないため、依然としてUMDファイル(Node限定のものを作成している場合はCommonJS)を配布する必要はあります。
ライブラリのpackage.jsonファイル(別名 pkg.module
)に、 "module": "dist/my-library.es.js"
というエントリを追加すると、すぐにUMDとES2015を同時に提供できます。 webpackとRollupは両方とも、最も効率的なコードを生成するために pkg.module
を使用するため、この点は重要です。 場合によっては、両者はライブラリの未使用部分を 削除 することもあります。
pkg.module
の詳細については Rollup wiki をご覧ください。
この記事を通じて、2つのプロジェクトの関係性を理解していただければ幸いです。疑問点がありましたら、Twitterで rich_harris 、 rollupjs 、または thelarkinn にご連絡ください。皆様が良いバンドリングツールと出会えますように。
この記事を書いてくださったRich Harris氏に感謝いたします。テクノロジーやウェブの発展には、オープンソースにおけるコラボレーションが欠かせないものとなっています。
webpackに貢献する時間はないけれども、別の方法で寄与したいという方は、 Open Collectiveに寄付 することで、webpackの後援者またはスポンサーになることができます。Open Collectiveでは、コアチームの支援に加え、我々の組織の発展のために多大なる時間を費やしているコントリビュータの皆様のサポートも行っています。
株式会社リクルート プロダクト統括本部 プロダクト開発統括室 グループマネジャー 株式会社ニジボックス デベロップメント室 室長 Node.js 日本ユーザーグループ代表
- Twitter: @yosuke_furukawa
- Github: yosuke-furukawa