なぜ Vite なのか

問題点

ES モジュールがブラウザで利用できるようになるまで、開発者はモジュール化された JavaScript を生成するネイティブの仕組みを持っていませんでした。これは、私たちが「バンドル」のコンセプトに慣れ親しんでいる理由でもあります: すなわち、ブラウザで実行可能なようにソースモジュールをクロール、処理し、連結するツールを使用しています。

時を経て webpackRollupParcel のようなツールが登場し、フロントエンド開発者の開発体験は大きく向上されました。

しかしながら、大規模なアプリケーションが作られるようになってくると、取り扱う JavaScript の量は指数関数的に増加しました。大規模プロジェクトでは、数千ものモジュールが含まれることも珍しくありません。JavaScript ベースのツールを使用していては、いずれパフォーマンスのボトルネックにぶつかります: 開発サーバを起動するのにやたらと長く待つこともあります(数分かかることさえ!)。また、HMR を利用していても、ファイル編集がブラウザに反映されるまで数秒かかることもあります。フィードバックの遅さが継続することは、開発者の生産性や幸福度に大きな影響を与える可能性があります。

Vite では新しいエコシステムの進歩を活用し、これらの問題を解決することに取り組んでいます: ブラウザのネイティブ ES モジュールや、ネイティブにコンパイルされる言語で書かれた先進的な JavaScript ツールの利用です。

遅いサーバ起動

開発サーバがコールドスタートするとき、バンドラベースのビルドセットアップは、アプリケーション全体を提供する前に、アプリケーション全体を隅々までクロールしてビルドする必要があります。

Vite はまず最初にアプリケーションのモジュールを 2 つのカテゴリに分割することで、開発サーバの起動時間を改善します: 依存関係ソースコードです。

  • 依存関係の大部分は開発中あまり変更されないプレーンな JavaScript です。巨大な依存関係の中には、処理コストが極めて高いものがあります(例: 100 ものモジュールを持つコンポーネントライブラリ)。依存関係は、様々なモジュール形式で出力されることがあります(例: ESM または CommonJS)。

    Vite は、esbuild を使用して依存関係の事前バンドルを行います。esbuild は Go 言語によって開発されており、依存関係の事前バンドルは、JavaScript ベースよりも 10 倍から 100 倍高速です。

  • ソースコードには変換を必要とするプレーンな JavaScript ではないものが含まれることがよくあり、頻繁に編集されます(例: JSX、CSS や Vue/Svelte コンポーネント)。また、全てのソースコードを同時に読み込む必要はありません(例: ルーティングによるコード分割)。

    Vite は、ネイティブ ESM を行使してソースコードを提供します。ブラウザは、実質的にバンドラの仕事の一部を引き受けます: Vite はブラウザのリクエストに応じて、ソースコードを変換し提供するのみになります。条件で囲われている動的インポートのコードは、現在の画面で使われる場合のみ処理されます。

    バンドラベースの開発サーバ

    esm ベースの開発サーバ

遅い更新速度

バンドラベースのビルドセットアップでファイルが編集されたとき、全てのバンドルを再構築することが非効率なことは明白です: 更新スピードはアプリケーションのサイズに応じて線形的に低下します。

バンドラの開発サーバではメモリ上でバンドルを実行するものがあります。それはファイルが変更されたとき、モジュールグラフの一部を無効にするだけですが、バンドル全体を再構築して、ウェブページをリロードしなければなりません。バンドルの再構築にはコストがかかりますし、ページリロードされるとアプリケーションの現在状態は消えてしまいます。そのため、幾つかのバンドラは HMR(ホットモジュールリプレースメント)をサポートしています: これにより、ページの変更に関係のない部分には影響を与えることなく、モジュールを「ホットリプレース」することができます。これは開発者体験を大きく改善します。- しかしながら、実際には HMR でもアプリケーションが大きくなるつれ更新速度が著しく悪化することは分かってきました。

Vite では、HMR をネイティブ ESM 上で行います。ファイルが編集されたとき、Vite は編集されたモジュールと最も近い HMR boundary 間のチェーンを厳密に無効化することで(大抵はモジュール本体だけです)、HMR による更新はアプリケーションのサイズに関係なく一貫して高速で実行されます。

また、Vite は HTTP ヘッダを活用して、フルページのリロードも高速化します (ここでも、ブラウザにはもっと働いてもらいます): ソースコードモジュールのリクエストでは 304 Not Modified を利用して条件が作成されます。そして、依存モジュールのリクエストでは、一度キャッシュされたものが再びサーバにヒットしないよう、Cache-Control: max-age=31536000,immutable を利用して積極的にキャッシュされます。

超高速な Vite を一度体験してしまうと、バンドルでの開発にまた耐えられるかはとても疑わしいです。

プロダクションではバンドルする理由

ネイティブ ESM が広くサポートされるようになっても、プロダクションでアンバンドルされた ESM を出力することは非効率です(HTTP/2 を利用していても)。これは、ネットワークのラウンドトリップの増加がネストされたインポートによって引き起こされるためです。プロダクションでは最適化されたローディングパフォーマンスは得るために、コードをツリー・シェイキングや遅延読み込み、共通な塊に分割することは、より良いことです(より良いキャッシングのために)。

開発サーバとプロダクションビルド間で、最適化された出力と一貫した動作を確保することは容易なことではありません。そのため、Vite にはあらかじめ調整されたビルドコマンドが用意されており、これには従来の常識を破る多くのパフォーマンス最適化が施されています。

なぜ esbuild でバンドルしないのか?

esbuild は超高速で、ライブラリをバンドルする事に関して大変有効な機能を確立していますが、_アプリケーション_をバンドルするために必要とされる重要な機能のいくつかは、開発途中です - 特にコード分割や CSS の処理です。当面の間は、Rollup の方がこれらの点において、より柔軟で成熟しています。そうはいっても、将来これらの機能が安定してきた場合、esbuild を使ってプロダクションビルドをする可能性は否定できません。

Vite とその他 X はどう違いますか?

Vite がその他の類似ツールとどう違うのか、より詳細な違いは、比較 セクションで確認してください。