Viteを選ぶ理由
問題点
ブラウザでESモジュールが利用可能になる前は、開発者はモジュール化された方法でJavaScriptを記述するためのネイティブなメカニズムを持っていませんでした。これが、私たち全員が「バンドリング」という概念に精通している理由です。ソースモジュールをクロール、処理、連結して、ブラウザで実行できるファイルを作成するツールを使用することです。
時とともに、webpack、Rollup、Parcelなどのツールが登場し、フロントエンド開発者の開発エクスペリエンスを大幅に向上させました。
しかし、より野心的なアプリケーションを構築するにつれて、扱うJavaScriptの量も劇的に増加しています。大規模なプロジェクトでは、数千ものモジュールが含まれることは珍しくありません。JavaScriptベースのツールのパフォーマンスのボトルネックに遭遇し始めています。開発サーバーの起動に不当に長い時間(数分かかることも!)がかかることが多く、ホットモジュール置換(HMR)を使用しても、ファイルの編集がブラウザに反映されるまでに数秒かかる場合があります。フィードバックループが遅いことは、開発者の生産性と満足度に大きな影響を与えます。
Viteは、エコシステムにおける新たな進歩、つまりブラウザでのネイティブESモジュールの可用性と、ネイティブコンパイル言語で記述されたJavaScriptツールの台頭を活用することで、これらの問題に対処することを目指しています。
サーバーの起動が遅い
開発サーバーをコールドスタートする場合、バンドラベースのビルド設定では、アプリケーション全体を熱心にクロールしてビルドしてから提供する必要があります。
Viteは、アプリケーション内のモジュールを最初に2つのカテゴリ、「依存関係」と「ソースコード」に分割することで、開発サーバーの起動時間を短縮します。
依存関係は、ほとんどがプレーンなJavaScriptであり、開発中はほとんど変更されません。大規模な依存関係(数百ものモジュールを持つコンポーネントライブラリなど)の処理も非常にコストがかかります。依存関係は、さまざまなモジュール形式(ESMやCommonJSなど)で提供される場合があります。
Viteは、依存関係をプリバンドルするためにesbuildを使用します。esbuildはGoで記述されており、JavaScriptベースのバンドラよりも10〜100倍高速に依存関係をプリバンドルします。
ソースコードには、多くの場合、変換が必要なプレーンでないJavaScript(JSX、CSS、Vue/Svelteコンポーネントなど)が含まれており、頻繁に編集されます。また、すべてのソースコードを同時にロードする必要はありません(ルートベースのコード分割など)。
Viteは、ネイティブESMを介してソースコードを提供します。これは本質的に、バンドラの仕事の役割の一部をブラウザに委任することです。Viteは、ブラウザが要求したときにのみ、ソースコードを変換して提供する必要があります。条件付きの動的インポートの背後にあるコードは、現在の画面で使用されている場合にのみ処理されます。
更新が遅い
バンドラベースのビルド設定でファイルが編集されると、明白な理由から、アプリケーション全体を再構築することは非効率的です。更新速度は、アプリケーションのサイズとともに線形に低下します。
一部のバンドラでは、開発サーバーはメモリ内でバンドリングを実行するため、ファイルの変更時にモジュールグラフの一部だけを無効にする必要がありますが、それでもバンドル全体を再構築してWebページをリロードする必要があります。バンドルの再構築はコストがかかる可能性があり、ページのリロードはアプリケーションの現在の状態を消去します。そのため、一部のバンドラはホットモジュール置換(HMR)をサポートしています。モジュールがページの残りの部分に影響を与えることなく、自身を「ホット置換」できるようにします。これにより、DXが大幅に向上しますが、実際には、アプリケーションのサイズが大きくなるにつれて、HMRの更新速度も大幅に低下することがわかりました。
Viteでは、HMRはネイティブESMを介して実行されます。ファイルが編集されると、Viteは編集されたモジュールとその最も近いHMR境界の間のチェーン(ほとんどの場合、モジュール自体のみ)を正確に無効にするだけで済みます。そのため、アプリケーションのサイズに関係なく、HMRの更新速度は常に高速です。
Viteは、HTTPヘッダーも活用して、完全なページのリロードを高速化します(これも、ブラウザにより多くの作業をさせる)。ソースコードモジュールの要求は、`304 Not Modified`を介して条件付きで行われ、依存関係モジュールの要求は`Cache-Control: max-age=31536000,immutable`を介して強くキャッシュされるため、一度キャッシュされるとサーバーに再度ヒットしません。
Viteの速度を体験したら、バンドルされた開発に戻したくなくなるでしょう。
本番環境でバンドルする理由
ネイティブESMは現在広くサポートされていますが、ネストされたインポートによって追加のネットワークラウンドトリップが発生するため、本番環境でバンドルされていないESMを出荷することは依然として非効率的です(HTTP/2でも)。本番環境で最適な読み込みパフォーマンスを得るには、ツリーシェイキング、遅延読み込み、共通チャンクの分割(キャッシュの向上のため)を使用してコードをバンドルする方が依然として優れています。
開発サーバーと本番ビルド間の最適な出力と動作の一貫性を確保することは容易ではありません。そのため、Viteには、多くのパフォーマンス最適化をすぐに利用できる、事前に設定されたビルドコマンドが付属しています。
esbuildでバンドルしない理由
Viteは開発で一部の依存関係をプリバンドルするためにesbuildを利用していますが、本番ビルドのバンドラとしてesbuildを使用していません。
Viteの現在のプラグインAPIは、バンドラとして`esbuild`を使用することとは互換性がありません。`esbuild`の方が高速ですが、ViteによるRollupの柔軟なプラグインAPIとインフラストラクチャの採用は、エコシステムにおける成功に大きく貢献しました。現時点では、Rollupの方がパフォーマンスと柔軟性のバランスが良いと考えています。
Rollupもパフォーマンスの改善に取り組んでおり、v4でパーサーをSWCに切り替えました。そして、RollupのRustポートであるRolldownを構築する取り組みも進行中です。Rolldownが準備できたら、ViteでRollupとesbuildの両方を置き換えることができ、ビルドのパフォーマンスが大幅に向上し、開発とビルド間の矛盾がなくなります。Evan YouによるViteConf 2023の基調講演で詳細をご覧ください。
ViteとXの違い
Viteが他の同様のツールとどのように異なるかについては、比較セクションをご覧ください。