Module Bundler とは
Module Bundler とは、多数の JavaScript コードファイルを 1 つに結合し、ブラウザーでの読み込みを可能にさせるツールです。
これから Module Bundler の歴史を振り返り、選定基準について私なりの考えを述べさせていただけたらと思います。
Browserify
Browserify
は 2010 年、最初に誕生した Module Bundler です。
- 2010 年当時、流行っていた Node.js をブラウザで使いたい
require
を用いてブラウザで動かす JS をモジュール分割したい
といったモチベーションの元で生まれました。
主な機能(Browserify)
CommonJS
(Node.js)で書かれたファイルをブラウザで読み込める JS に結合してくれます
課題(Browserify)
後述しますが、バンドル対象が CommonJS
のみであり、バンドルする際の手順を組みたい場合はGulp
などのタスクランナーに依存する必要があります。
Webpack
Webpack
は 2012 年に誕生し、State of JS 2022でも Retention が 2022 時点で 63.3%、npm trends のダウンロード数でも他の Module bundler を突き放して 1 位と、現在最も利用されている成熟したモジュールバンドラーです。
主な機能(Webpack)
ES Module
,CommonJS
などのモジュールに加え、CSS や画像などのアセットファイルも読み込み、バンドルすることができますAngular
,Vue
,React
などが内部で利用しており、サードパーティツールが非常に多い
Browserify との比較
登場年 | バンドル対象 | バンドルフロー | コード分割 | |
---|---|---|---|---|
Browserify | 2011 | CJS | Gulp などのタスクランナーを利用してバンドル手順を決定する | プラグインに依存する |
Webpack | 2012 | CJS, HTML, CSS, 画像などアセットファイルも含む | config ファイルを使用してバンドルの手順を決定する | コード分割機能が組み込まれている |
Webpack
は Browserify
と比較して、バンドル対象が増え、config ファイルに記載することでタスクランナーの代替になるような使い方もできます。設定次第でかなり柔軟な使い方ができ、それが現在まで使われてきた理由かもしれません。
課題(Webpack)
config ファイルで柔軟な使い方ができるといったトレードオフで、config ファイルが複雑になりやすいといった課題があります。
また、それに伴い学習コストが他の Module Bundler に比べて高いということも考えられます。
Parcel
Parcel
は Zero configuration build tool を謳い文句にした Module bundler です。
主な機能(Parcel)
- 設定ファイル不要
- JavaScript, CSS transformer などが
Rust
で書かれており、通常の JavaScript でのツールに比べて 10~20 倍のビルド速度 - キャッシュにより 2 回目以降はビルドされずに高速に開発できる
課題(Parcel)
- 最初にアプリケーションをバンドルする速度は
Webpack
に劣る - サードパーティツールが
Webpack
に比べて少ない
https://levelup.gitconnected.com/parcel-vs-webpack-2021-64c347bcb31
やりたいことが複雑化してきたり、大規模なアプリケーションになればなるほど、Webpack
を使う方がいいかもしれません。
しかし、小規模のアプリケーションであれば Zero configuration の恩恵が大きいので Parcel
を使う選択肢も視野に入れるのもいいでしょう。
Rollup
Rollup
も Webpack
と同様に現在でもかなり人気のある(npm trends ではダウンロード数が 3 位)成熟した Module Bundler で 2015 年に登場しました。
開発背景が Webpack
とは異なり、Rollup
は「ES2015 のモジュールを活用し、一様に配布でき、できるだけ効率的な JavaScript ライブラリを作成可能する」という背景で生まれました。
https://medium.com/webpack/webpack-and-rollup-the-same-but-different-a41ad427058c
主な機能(Rollup)
ES6
を前提にバンドル化する(Webpack
はES5
前提)- 上記により静的解析を行うことができるため一括でモジュールの評価ができ、起動が高速
Webpack
では評価時にモジュールを関数にラップし、バンドルに含めるために各ブラウザに合ったrequire
の実装を内部で行うのでモジュールが増えるごとに無駄な処理が走る- 上記によりデッドコード(使用していないコード)を除去する Tree shaking が働く
- 大きく複雑なコードを小さなコードにコンパイルする
Webpack との比較(Rollup)
登場年 | バンドル前提 | 用途 | TreeShaking | HMR | |
---|---|---|---|---|---|
Rollup | 2016 | ES6 | ライブラリ | デフォルト | Nollup を使う必要 |
Webpack | 2012 | ES5 | アプリケーション | 設定が必要 | 対応 |
Webpack との大きな違いは前述した通りバンドル化する前提の規格が異なります。また、バンドル結果や Tree shaking などの観点からライブラリ向けの Module Bundler という使い分けもできます。
課題(Rollup)
比較からわかる通り、Rollup
は HMR
(Hot Module Replacement)に非対応で、外部のツールに頼る必要があります。
また、CommonJS
を ES2015
に変換できないケースもあるといった問題点もあります。
esbuild
esbuild
はそれ以前の Module bunder と比べて 10~100
倍近くビルド時間を高速化させた bundler です。
Go
で記述されている、並列処理の多様、メモリの効率化などににより高速化を実現しています。
主な機能(esbuild)
Webpack
と同様に
ESM
/CommonJS
モジュールをバンドル- 開発サーバーやプラグインのサポート
- Tree shaking, minification, source map をサポート
などをしており、
- キャッシュせずに高速のビルドを実現
JavaScript
,CSS
,TypeScript
,JSX
のローダーが既存で入っている
などがあります。
Webpack との比較(esbuild)
登場年 | バンドル速度 | 型チェック | HMR | コード分割 | 組み込みローダー | |
---|---|---|---|---|---|---|
esbuild | 2017 | 10~100 倍 | tsc を組み合わせる必要 | できない | 将来できる予定 | TypeScript, JSX など |
Webpack | 2012 | できる | できる | できる | なし |
課題(esbuild)
今後のロードマップより(2023 年 2 月)、
- コード分割
ES5
への変換- トップレベル
await
のバンドル
はまだ未対応(将来対応する予定)で、
HMR
TypeScript
の型チェックVue
,Elm
,Svetlen
,Angular
などのフロントエンドフレームワークサポート
などは今後も対応する予定がないとのことです。
これらから、上記の課題が当てはまらず、とにかくビルド速度を速くしたいプロダクトや、開発環境に向いているバンドラーだと考えられます。
Snowpack
Snowpack
は今までの Module Bundler と異なり、Native ESM Module
を活用して不要なバンドルをなくし、高速なビルドを行う Bundler です。
主な機能(Snowpack)
- 開発時はアンバンドルで提供
開発時はバンドルせずに、個々のファイルをブラウザに提供し、Babel
・TypeScript
・SASS
などのツールを用いてビルドされます。またこのファイルに変更があった場合、そのファイルのみをビルドし、アプリケーション全体をバンドルしないので、Webpack
などの既存のバンドラーと比べて無駄な時間が発生しません。
さらにビルドされたファイルは無期限にキャッシュされるので、ファイルが変更されるまでブラウザでダウンロードされることはなく、これも開発時のビルド速度を向上させています。
- 本番用にバンドルする際は
Snowpack
公式のプラグインを介して最適化できる - 開発サーバー・プラグインをサポート
JavaScript
,CSS
,TypeScript
,JSX
,React
などのローダーが組み込みで入っているァイルのみ再ビルドする。
注意点
2022 年 4 月メンテナンスが終了し、Vite
が推奨されています。(Snowpack チームは Astro の開発をしているらしいです。)
また、後述の Vite
は Snowpack
にインスパイアを受けているそうです。
https://ja.vitejs.dev/guide/comparisons.html
Vite
Vite
は Snowpack
の思想に影響を受け、Native ESModule
を用い、内部で開発時の依存関係は esbuild、本番時は Rollup を用いています。Vue
の作者が作っていることもあり、Vue
と相性が良いことも特徴の一つです。
主な機能(Vite)
- 開発時は全てバンドルを行わず依存関係 / ソースコードに分類して起動します。
esbuild
で依存関係の事前バンドルを行います。- ソースコードは
TypeScript
やJSX
などプレーンでないJavaScript
も含まれており、Vite
はこれをNative ESModule
に変換してブラウザに渡します。 - これにより編集したモジュールのみを更新し、全体をバンドルし直す必要がなくなります。
- プロダクションコードは最適化を行うために安定している
Rollup
を用いてバンドルを行います。 Native ESModule
を介してHMR API
を提供しているので、ファイルの更新時も高速に動作しますTypeScript
,Vue
,JSX
,CSS
などのファイルをサポート- プラグインのサポート
課題(Vite)
- 型チェックは行われないので、
tsc
などと組み合わせる必要
Turbopack
Turbopack
は 2022 年、Next.js
を運営している Vercel が Webpack
の後継として発表した Module Bundler です。
Rust
ベースで、大規模なアプリケーションであれば Webpack
の 700
倍近くの速度でコード更新が反映されるみたいです。Turbopack
が高速な主な理由としては、
- 関数レベル(呼び出されたもの・返されたもの)でメモリ内キャッシュする
- 開発サーバの実行開始を高速化するために、開始に必要なコードのみをコンパイルする
などが挙げられます。(これを Turbo build engine と呼びます)
将来的には、Webpack
のアプリケーションをサポートするための全てのツールを Turbopack
に移植する予定。また、人気のあるプラグインも移植する予定とのことです。
Native ES Module Bundler との違い
Vite
やなどの Native ES Module Bundler
は開発時にコードをバンドルしませんが、Turbopack
は開発時も Webpack
同様にアプリケーションコードをバンドルします。
これは大規模なアプリケーションであると、Vite
はスケーリングの問題に直面する可能性があるそうです。前述した Turbo engine を用いるとバンドルしても同じビルド処理を複数回行うことなく、バンドル時の無駄な処理が行われず、バンドルすることは問題にならないと述べられています。
課題(Turbopack)
- 2023 年 2 月時点、
Next13
でしか使えない - まだアルファ版
- プラグインなどもまだ使えない
結局何を使えばいいのか
アプリケーションの規模やフレームワーク・アウトプットの種類によって使い分ける必要があると考えます。以下は”相性がいい”程度の考えなので、参考程度にしてもらえるといいかと思います。(左からおすすめ順)
規模で考える場合
- 大規模 :
Vite
、Webpack
(安定性を考慮・のちにTurbopack
に移行を考える必要),Rollup
- 小〜中規模 :
Vite
、esbuild
、Parcel
フレームワークで考える場合
2022 年で利用率の高かったフレームワークに焦点を当てて考えます。
React(Next)
:Webpack
、Turbopack
(Next13
限定)、esbuild
、Rollup
、Parcel
Vue(Nuxt)
:Vite
、Webpack
、Rollup
、Parcel
アウトプットの種類で考える場合
ここではアプリケーション・ライブラリの 2 種類について考えます。
アプリケーション : Vite
、Webpack
、Parcel
、Rollup
、esbuild
ライブラリ : Rollup
、Vite
(本番ビルドは Rollup
のため)、Webpack