Vite

開発時はネイティブ ESM で配信し、本番はバンドラーでまとめるフロントエンド向けのビルドツール

ビルドフロントエンド
「Vite」の技術書を見る →

Vite とは

Vite (ヴィート、フランス語で「速い」) は、Evan You (Vue.js の作者) が 2020 年に公開したフロントエンド向けのビルドツールである。提供するものは 2 つで、開発中に使うローカルサーバーと、本番向けに一式をまとめるビルドコマンドである。この 2 つで前提が違うことが Vite を理解する鍵になる。開発時はブラウザーのネイティブ ESM をそのまま使って必要なファイルを要求のたびに変換して返し、本番ビルドではバンドラーで 1 つの依存グラフとしてまとめる。設定ファイルは共通なので、利用側から見ると 1 つのツールとして扱える。

開発サーバーが速い理由

「バンドルしないから速い」という説明は正確ではない。Vite は開発時にコードを 2 種類に分けて扱う。

  • 依存 (node_modules のライブラリ) は変更が少ないため、ネイティブのツールで一度だけ事前バンドルしておく。
  • 自分で書いたソースはネイティブ ESM でオンデマンドに配信し、ブラウザーが要求した時点でそのファイルだけを変換する。

つまり、ブラウザーは今表示しているページに必要な分だけを読み込む。ソース全体を事前に走査してひとまとめにする工程が起動時に無いので、行数が増えても起動時間が同じようには伸びない。

バンドル前提の開発サーバー:
  起動時に依存グラフをたどってまとめる → まとまってから配信を始める

Vite の開発サーバー:
  依存は起動前に一度だけ事前バンドル
  ソースはブラウザの要求ごとに 1 ファイル変換して返す

代償もある。依存を追加した直後は事前バンドルがやり直されるため、その回だけ初回アクセスが待たされる。また開発時と本番ビルドで通る経路が違うので、開発では動くのに本番ビルドだけ壊れるという差異が原理的に生じ得る。この経路の不一致は Vite 自身が課題として挙げてきた点でもある。

HMR の機序

HMR (Hot Module Replacement) は、変更されたモジュールをネイティブ ESM 上で差し替えることで、ページ全体の再読み込みやリビルドの待ち時間なしに画面へ反映する仕組みである。ここで重要なのは、差し替えを受け入れるモジュールが必要だという点である。

import.meta.hot.accept() を呼んだモジュールが更新の受け入れ先になり、受け入れ先が見つからない場合は更新が読み込み元へ遡り、最終的にページ全体の再読み込みになる。自分で受け入れたつもりでも実行時に処理しきれないと判断した場合は import.meta.hot.invalidate() で読み込み元へ差し戻せる。この API を直接書く場面は多くない。フレームワーク向けのプラグインが受け入れ処理を用意しており、React であれば Fast Refresh として状態を保ったままの差し替えを担当する。

「保存したのに毎回ページ全体が再読み込みされる」という症状は、受け入れ先が無いモジュール (副作用を持つ設定ファイル等) を編集していることが多い。

本番ビルドの基盤 (2026 年 8 月時点)

本番ビルドを担うバンドラーは、Vite 8 (2026 年 3 月公開) で Rolldown に統一された。それ以前は開発時の変換と事前バンドルを esbuild、本番バンドルを Rollup が担う 2 本立てで、2 つのパイプラインを保守する構造そのものが不一致の温床だった。Rolldown は Rust 製で、Rollup と同じプラグイン API を持つため既存プラグインの多くはそのまま動く。公式発表はビルドが最大 10 倍から 30 倍速くなるとしており、parse / 変換 / minify は Oxc が担当する。

移行にあたって影響が出やすい設定は次の 2 点である。build.rollupOptions は build.rolldownOptions の別名として残っているが非推奨で、output.manualChunks のオブジェクト形は廃止 (関数形も非推奨) され、chunk の分割は Rolldown 側の codeSplitting を使う形になった。開発時もバンドルする Full Bundle Mode は同時に導入されたが、こちらは実験的な機能である。

バンドラーが何をするかは バンドラー、使われていないコードの除去は tree shaking を参照。

webpack と比べるときの判断軸

起動時間の秒数を並べても、プロジェクトの規模と依存の数で結果が変わるため判断材料にならない。見るべきは前提の違いである。

観点Vitewebpack
開発時の配信依存は事前バンドル、ソースはネイティブ ESM でオンデマンド変換依存グラフをまとめてから配信
設定の書き方既定値が用意され、変えたい部分だけ書くloader と plugin を組んで変換経路を定義する
TypeScript変換は組み込み (型検査は別途)ts-loader や babel-loader を選ぶ
本番バンドラーRolldown (Vite 8 以降)webpack 自身
ブラウザー前提開発時にネイティブ ESM が必要出力形式を選べる

選定で実際に効くのは、使うフレームワークに対応するプラグインが維持されているか、既存の webpack 設定に置き換えの効かない独自 loader が含まれていないかである。設定を細かく制御してきた既存プロジェクトでは、その制御をどの機構に移すかが移行コストの本体になる。

TypeScript は変換だけで型検査はしない

Vite は .ts ファイルを変換するが型検査は行わない。公式ドキュメントも型検査は IDE とビルド工程の担当と明言している。変換はファイル単位で完結するためオンデマンド配信と噛み合うが、型検査はプロジェクト全体の情報を必要とするので、ファイル単位の変換の途中に挟めないためである。

ここを知らないと、型エラーがあるコードがビルドを通ってしまう。対処は工程を分けることで、本番ビルドでは tsc --noEmit を併走させ、開発中に IDE の表示以上が必要なら tsc --noEmit --watch を別プロセスで動かすか、ブラウザー上に型エラーを出す vite-plugin-checker を使う。

tsconfig.json の isolatedModules は true にしておく。型情報を使わない変換では const enum や暗黙の型のみ import のような機能を扱えないため、これを有効にして事前に警告させる必要がある。詳しくは TypeScript を参照。

設定の書き方

設定でよく触るのは、フレームワーク向けプラグインの登録、開発サーバーのポートとプロキシ、出力先とソースマップの 3 か所である。

// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  server: {
    port: 3000,
    proxy: {
      // 開発時だけ API を別プロセスへ転送する (CORS 設定を避けられる)
      '/api': 'http://localhost:4000',
    },
  },
  build: {
    outDir: 'dist',
    sourcemap: true,
  },
});

server.proxy は開発サーバーの機能なので、本番では同じ転送は起きない。本番では配信側 (CDN やリバースプロキシ) に同じ経路を用意する必要があり、ここを忘れると開発だけ動く状態になる。

Vitest との統合

Vitest は既定で vite.config.* を読む。そのため Vite 側に登録したプラグインと解決設定がテスト実行時にも効き、テスト用に変換設定を書き直す必要がない。テスト固有の設定を分けたい場合は vitest.config.* を置く。

// vitest.config.ts (テスト固有の設定を分ける場合)
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    globals: true,
    environment: 'jsdom',
  },
});

設定を共有できる利点は、テストと本番で違う変換を通したせいでテストだけ通る (あるいはテストだけ落ちる) 事故が起きにくいことにある。

フレームワーク対応 (2026 年 8 月時点)

Vite が公式プラグインとして提供しているのは Vue と React 系である。Vue は @vitejs/plugin-vue と JSX 用の @vitejs/plugin-vue-jsx、React は Fast Refresh を Oxc Transformer 経由で提供する @vitejs/plugin-react があり、SWC のプラグインを使いたい場合は開発時の変換を差し替える @vitejs/plugin-react-swc を選ぶ。React Server Components 向けには @vitejs/plugin-rsc が用意されている。

Svelte の @sveltejs/vite-plugin-svelte と Solid の vite-plugin-solid は Vite 公式一覧の外にあり、それぞれのコミュニティ側で維持されている。この違いは、対応が切れたときに誰が直すかという保守の見通しに関わるので、採用時には確認しておく価値がある。

全体像を把握するには関連書籍も有用。

共有:

この記事は役に立ちましたか?

関連用語

関連する記事