Module Bundlerの歴史を振り返って今採用すべきBundlerを考える

Posted: 2023/2/15

Module Bundler とは

Module Bundler とは、多数の JavaScript コードファイルを 1 つに結合し、ブラウザーでの読み込みを可能にさせるツールです。

これから Module Bundler の歴史を振り返り、選定基準について私なりの考えを述べさせていただけたらと思います。

Browserify

Browserify は 2010 年、最初に誕生した Module Bundler です。

  • 2010 年当時、流行っていた Node.js をブラウザで使いたい
  • requireを用いてブラウザで動かす JS をモジュール分割したい

といったモチベーションの元で生まれました。

Browserify

https://browserify.org/

主な機能(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 などが内部で利用しており、サードパーティツールが非常に多い

webpack

https://webpack.js.org/

Browserify との比較

登場年バンドル対象バンドルフローコード分割
Browserify2011CJSGulp などのタスクランナーを利用してバンドル手順を決定するプラグインに依存する
Webpack2012CJS, HTML, CSS, 画像などアセットファイルも含むconfig ファイルを使用してバンドルの手順を決定するコード分割機能が組み込まれている

WebpackBrowserify と比較して、バンドル対象が増え、config ファイルに記載することでタスクランナーの代替になるような使い方もできます。設定次第でかなり柔軟な使い方ができ、それが現在まで使われてきた理由かもしれません。

課題(Webpack)

config ファイルで柔軟な使い方ができるといったトレードオフで、config ファイルが複雑になりやすいといった課題があります。

また、それに伴い学習コストが他の Module Bundler に比べて高いということも考えられます。

Parcel

Parcel は Zero configuration build tool を謳い文句にした Module bundler です。

Parcel

https://parceljs.org/

主な機能(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

RollupWebpack と同様に現在でもかなり人気のある(npm trends ではダウンロード数が 3 位)成熟した Module Bundler で 2015 年に登場しました。

開発背景が Webpack とは異なり、Rollup は「ES2015 のモジュールを活用し、一様に配布でき、できるだけ効率的な JavaScript ライブラリを作成可能する」という背景で生まれました。

https://medium.com/webpack/webpack-and-rollup-the-same-but-different-a41ad427058c

主な機能(Rollup)

  • ES6 を前提にバンドル化する(WebpackES5 前提)
  • 上記により静的解析を行うことができるため一括でモジュールの評価ができ、起動が高速
    • Webpack では評価時にモジュールを関数にラップし、バンドルに含めるために各ブラウザに合った requireの実装を内部で行うのでモジュールが増えるごとに無駄な処理が走る
    • 上記によりデッドコード(使用していないコード)を除去する Tree shaking が働く
  • 大きく複雑なコードを小さなコードにコンパイルする

Webpack との比較(Rollup)

登場年バンドル前提用途TreeShakingHMR
Rollup2016ES6ライブラリデフォルトNollup を使う必要
Webpack2012ES5アプリケーション設定が必要対応

Webpack との大きな違いは前述した通りバンドル化する前提の規格が異なります。また、バンドル結果や Tree shaking などの観点からライブラリ向けの Module Bundler という使い分けもできます。

https://postd.cc/webpack-and-rollup-the-same-but-different/

課題(Rollup)

比較からわかる通り、RollupHMR(Hot Module Replacement)に非対応で、外部のツールに頼る必要があります。

また、CommonJSES2015 に変換できないケースもあるといった問題点もあります。

esbuild

esbuild はそれ以前の Module bunder と比べて 10~100 倍近くビルド時間を高速化させた bundler です。

Go で記述されている、並列処理の多様、メモリの効率化などににより高速化を実現しています。

主な機能(esbuild)

Webpack と同様に

  • ESM / CommonJS モジュールをバンドル
  • 開発サーバーやプラグインのサポート
  • Tree shaking, minification, source map をサポート

などをしており、

  • キャッシュせずに高速のビルドを実現
  • JavaScript, CSS, TypeScript, JSX のローダーが既存で入っている

などがあります。

Webpack との比較(esbuild)

登場年バンドル速度型チェックHMRコード分割組み込みローダー
esbuild201710~100 倍tsc を組み合わせる必要できない将来できる予定TypeScript, JSX など
Webpack2012できるできるできるなし

課題(esbuild)

今後のロードマップより(2023 年 2 月)、

  • コード分割
  • ES5 への変換
  • トップレベル await のバンドル

はまだ未対応(将来対応する予定)で、

  • HMR
  • TypeScript の型チェック
  • Vue, Elm, Svetlen, Angular などのフロントエンドフレームワークサポート

などは今後も対応する予定がないとのことです。

これらから、上記の課題が当てはまらず、とにかくビルド速度を速くしたいプロダクトや、開発環境に向いているバンドラーだと考えられます。

Snowpack

Snowpack は今までの Module Bundler と異なり、Native ESM Module を活用して不要なバンドルをなくし、高速なビルドを行う Bundler です。

主な機能(Snowpack)

  • 開発時はアンバンドルで提供

開発時はバンドルせずに、個々のファイルをブラウザに提供し、BabelTypeScriptSASS などのツールを用いてビルドされます。またこのファイルに変更があった場合、そのファイルのみをビルドし、アプリケーション全体をバンドルしないので、Webpack などの既存のバンドラーと比べて無駄な時間が発生しません。

さらにビルドされたファイルは無期限にキャッシュされるので、ファイルが変更されるまでブラウザでダウンロードされることはなく、これも開発時のビルド速度を向上させています。

snowpack

https://www.snowpack.dev/concepts/how-snowpack-works

  • 本番用にバンドルする際は Snowpack 公式のプラグインを介して最適化できる
  • 開発サーバー・プラグインをサポート
  • JavaScript, CSS, TypeScript, JSX, React などのローダーが組み込みで入っているァイルのみ再ビルドする。

How Snowpack Works

https://blog.sessionstack.com/understanding-snowpack-the-next-generation-javascript-bundler-c541a3efe54d

注意点

2022 年 4 月メンテナンスが終了し、Vite が推奨されています。(Snowpack チームは Astro の開発をしているらしいです。)

また、後述の ViteSnowpack にインスパイアを受けているそうです。

https://ja.vitejs.dev/guide/comparisons.html

Vite

ViteSnowpack の思想に影響を受け、Native ESModule を用い、内部で開発時の依存関係は esbuild、本番時は Rollup を用いています。Vue の作者が作っていることもあり、Vue と相性が良いことも特徴の一つです。

主な機能(Vite)

  • 開発時は全てバンドルを行わず依存関係 / ソースコードに分類して起動します。
    • esbuild で依存関係の事前バンドルを行います。
    • ソースコードは TypeScriptJSX などプレーンでない 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 ベースで、大規模なアプリケーションであれば Webpack700 倍近くの速度でコード更新が反映されるみたいです。Turbopack が高速な主な理由としては、

  • 関数レベル(呼び出されたもの・返されたもの)でメモリ内キャッシュする
  • 開発サーバの実行開始を高速化するために、開始に必要なコードのみをコンパイルする

などが挙げられます。(これを Turbo build engine と呼びます)

https://turbo.build/pack/docs/core-concepts

将来的には、Webpack のアプリケーションをサポートするための全てのツールを Turbopack に移植する予定。また、人気のあるプラグインも移植する予定とのことです。

https://turbo.build/pack/docs/migrating-from-webpack

Native ES Module Bundler との違い

Vite やなどの Native ES Module Bundler は開発時にコードをバンドルしませんが、Turbopack は開発時も Webpack 同様にアプリケーションコードをバンドルします。

これは大規模なアプリケーションであると、Vite はスケーリングの問題に直面する可能性があるそうです。前述した Turbo engine を用いるとバンドルしても同じビルド処理を複数回行うことなく、バンドル時の無駄な処理が行われず、バンドルすることは問題にならないと述べられています。

https://turbo.build/pack/docs/why-turbopack

課題(Turbopack)

  • 2023 年 2 月時点、Next13 でしか使えない
  • まだアルファ版
  • プラグインなどもまだ使えない

結局何を使えばいいのか

アプリケーションの規模やフレームワーク・アウトプットの種類によって使い分ける必要があると考えます。以下は”相性がいい”程度の考えなので、参考程度にしてもらえるといいかと思います。(左からおすすめ順)

規模で考える場合

  • 大規模 : ViteWebpack(安定性を考慮・のちに Turbopack に移行を考える必要), Rollup
  • 小〜中規模 : ViteesbuildParcel

フレームワークで考える場合

2022 年で利用率の高かったフレームワークに焦点を当てて考えます。

  • React(Next) : WebpackTurbopack(Next13 限定)、esbuildRollupParcel
  • Vue(Nuxt) : ViteWebpackRollupParcel

アウトプットの種類で考える場合

ここではアプリケーション・ライブラリの 2 種類について考えます。

アプリケーション : ViteWebpackParcelRollupesbuild

ライブラリ : RollupVite(本番ビルドは Rollup のため)、Webpack