Skip to content

Vite を使う理由

Web アプリケーションの規模と複雑さが増すにつれ、それを構築するためのツールはついていくのが難しくなってきました。大規模プロジェクトで働く開発者は、耐えられないほど遅い開発サーバーの起動、もたつくホット更新、長い本番ビルド時間に悩まされてきました。ビルドツールの世代は更新されるたびに改善されてきましたが、これらの問題は解消されませんでした。

Vite はこの問題に取り組むために作られました。既存のアプローチを段階的に改善するのではなく、開発中にコードをどのように提供すべきかを根本から再考しました。それ以来、Vite は複数のメジャーバージョンを経て進化し、そのたびにエコシステムの新しい機能に対応してきました: ブラウザーのネイティブ ES モジュールの活用から、完全 Rust 製ツールチェーンの採用まで。

今日、Vite は多くのフレームワークやツールを支えています。そのアーキテクチャーは特定のアプローチに縛られることなく、Web プラットフォームとともに進化するよう設計されており、長期的に構築できる基盤となっています。

誕生の背景

Vite が最初に作られた当時、ブラウザーは ES モジュール(ESM)への幅広いサポートをちょうど獲得したばかりでした。ESM は JavaScript ファイルを直接読み込む方法で、ひとつのファイルにバンドルするツールを必要としません。従来のビルドツール(よく「バンドラー」と呼ばれます)は、ブラウザーに何かを表示する前にアプリケーション全体を処理する必要がありました。アプリが大きくなるほど、待ち時間が長くなっていました。

Vite は異なるアプローチをとりました。作業を 2 つに分けたのです:

  • 依存関係(ほとんど変更されないライブラリー)は、高速なネイティブツールを使って一度だけ事前バンドルされるため、即座に利用できます。
  • ソースコード(頻繁に変更するアプリケーションコード)はネイティブ ESM によってオンデマンドで提供されます。ブラウザーは現在のページに必要なものだけを読み込み、Vite はリクエストされたファイルをそのたびに変換します。

これにより、アプリケーションのサイズに関わらず、開発サーバーの起動がほぼ瞬時になりました。ファイルを編集すると、Vite はネイティブ ESM 上の Hot Module Replacement(HMR)を使い、フルページリロードや再ビルドを待つことなく、そのモジュールだけをブラウザーで更新します。

バンドルベースの開発サーバー entry ··· route route module module module module ··· Bundle Server ready

バンドラーベースの開発サーバーでは、アプリケーション全体がバンドルされてから提供される。

ネイティブ ESM ベースの開発サーバー entry ··· route route module module module module ··· Server ready 動的インポート (コード分割点) HTTP リクエスト

ESM ベースの開発サーバーでは、モジュールはブラウザーのリクエストに応じてオンデマンドで提供される。

このアプローチを最初に探求したのは Vite ではありません。Snowpack は非バンドル開発を先駆けて実現し、Vite の依存関係事前バンドルにインスピレーションを与えました。Preact チームの WMR は、開発とビルドの両方で機能するユニバーサルプラグイン API に影響を与えました。@web/dev-server は Vite 1.0 のサーバーアーキテクチャーに影響を与えました。Vite はこれらのアイデアを土台にして、さらに発展させました。

非バンドルの ESM は開発時にはうまく機能しますが、本番環境での配布はネストされたインポートによる追加のネットワークラウンドトリップが発生するため、依然として非効率です。最適化された本番ビルドにはバンドルが依然として必要な理由があるのはそのためです。

エコシステムとともに成長する

Vite が成熟するにつれ、フレームワークはそのビルドレイヤーとして採用し始めました。Rollup の規約に基づいたプラグイン API により、フレームワークが Vite の内部を回避する必要なく、自然に統合できるようになりました。NuxtSvelteKitAstroReact RouterAnalogSolidStart などが Vite を基盤として選択しました。VitestStorybook といったツールもその上に構築され、Vite の活用範囲をアプリのバンドル以外にも広げました。LaravelRuby on Rails といったバックエンドフレームワークも、フロントエンドアセットパイプラインに Vite を統合しました。

この成長は一方向ではありませんでした。エコシステムが Vite を形成したのと同様に、Vite もエコシステムを形成しました。Vite チームは vite-ecosystem-ci を運営しており、Vite のすべての変更に対して主要なエコシステムプロジェクトをテストしています。エコシステムの健全性は後付けの考慮事項ではありません。それはリリースプロセスの一部です。

統一されたツールチェーン

Vite はもともと内部で 2 つの別々のツールに依存していました: 開発時の高速なコンパイルには esbuild、本番ビルドの徹底的な最適化には Rollup です。これは機能していましたが、2 つのパイプラインを維持することで不整合が生じました: 異なる変換の動作、別々のプラグインシステム、両者を整合させるための増え続けるグルーコード。

Rolldown は両者をひとつのバンドラーに統合するために作られました: ネイティブ速度のために Rust で書かれ、エコシステムがすでに依存していた同じプラグイン API と互換性があります。パース、変換、ミニファイには Oxc を使用します。これにより Vite は、ビルドツール、バンドラー、コンパイラーが一緒にメンテナンスされ、一体として進化するエンドツーエンドのツールチェーンを手に入れました。

結果は、開発から本番まで一貫したパイプラインです。移行は慎重に行われました: 早期採用者が変更を検証できるようテクニカルプレビューが先に公開され、エコシステム CI が互換性の問題を早期にキャッチし、互換性レイヤーが既存の設定を保持しました。

Vite の今後

Vite のアーキテクチャーは進化し続けています。いくつかの取り組みがその将来を形作っています:

  • フルバンドルモード: 非バンドルの ESM は Vite が作られた当時、開発中にバンドルするために必要な HMR とプラグイン機能を備えながら十分に速いツールが存在しなかったため、正しいトレードオフでした。Rolldown はそれを変えます。非常に大規模なコードベースでは、バンドルされていないネットワークリクエストの数が多いためページ読み込みが遅くなることがあるため、開発サーバーが本番と同様にコードをバンドルするモードを探求しており、ネットワークオーバーヘッドを削減します。

  • Environment API:「クライアント」と「SSR」だけを 2 つのビルドターゲットとして扱うのではなく、Environment API により、フレームワークはカスタム環境(エッジランタイム、サービスワーカー、その他のデプロイターゲット)を定義でき、それぞれが独自のモジュール解決と実行ルールを持てます。コードが実行される場所と方法が多様化し続けるにつれ、Vite のモデルもそれに合わせて拡張されます。

  • JavaScript とともに進化する: Oxc と Rolldown が Vite と密接に協力することで、新しい言語機能や標準を、上流の依存関係を待つことなく、ツールチェーン全体に迅速に採用できます。

Vite の目標は最終的なツールになることではなく、Web プラットフォームとともに、そしてその上に構築する開発者とともに、進化し続けることです。