Vite
Viteとは
Vite(ヴィート、フランス語で「速い」)は、フロントエンド開発のためのビルドツールです。開発中は ES Modules をそのまま配信することで爆速の起動・更新を実現し、本番ビルドでは Rollup ベースで最適化します。
npm create vite@latest my-app
cd my-app && npm install && npm run dev # 一瞬で起動する
初学者向けポイント
- 「ビルドツール」= [[TypeScript]] やJSXなどブラウザが直接理解できないコードを変換し、ファイルをまとめる道具
- HMR(Hot Module Replacement)= 保存した瞬間、ページ全体をリロードせずに変更部分だけ差し替わる
import.meta.globで「フォルダ内のファイルを一括読み込み」のような便利機能もある(Markdownの記事群をまとめて取り込む、といった用途)
なぜ起動が速いのか
従来のバンドラは、開発サーバーを立ち上げる前にアプリ全体を1つの束にまとめていました。ファイルが増えるほど起動待ちが伸び、規模によっては起動だけで数十秒〜数分かかることもあります。
Vite はこの順序を逆にします。ブラウザは ES Modules を直接読めるので、開発中はまとめる作業をせず、ブラウザが要求したファイルだけをその場で変換して返すという方針です。まだ開いていない画面のコードは変換すらされないため、プロジェクトが大きくなっても起動時間はほとんど伸びません。HMR が速いのも同じ理屈で、保存したファイルとその周辺だけを差し替えます。
ただし node_modules の中身は例外です。ライブラリは内部で数百のファイルに分かれていることがあり、そのまま配ると1画面の表示で何百回もリクエストが飛んでしまいます。そこで Vite は初回起動時に依存ライブラリだけを esbuild でまとめて変換しておきます(依存の事前バンドル)。パッケージを追加した直後の起動だけ少し待たされるのは、この処理が走り直すためです。
従来ツールとの違い
| 観点 | 従来(webpack など) | Vite |
|---|---|---|
| 開発サーバー起動 | 全体をバンドルしてから起動 | バンドルせず即起動 |
| 更新反映 | 依存が多いと遅くなりがち | 変更モジュールだけ変換 |
| 設定 | 複雑になりやすい | デフォルトで大半をカバー |
つまずきやすいところ
型エラーはビルドを止めない — Vite は TypeScript の型注釈を取り除くだけで、型が正しいかは検査しません。そのため vite build は型エラーが残っていても成功してしまいます。多くのプロジェクトが package.json に "build": "tsc -b && vite build" と書いているのはこのためで、型チェックは別の道具の担当です。「エディタは赤いのにビルドは通る」ときは、この分担を思い出してください。
環境変数は VITE_ で始めないと読めない — ブラウザ側のコードに渡るのは import.meta.env.VITE_API_URL のように VITE_ を前置きした変数だけです。API_URL=... と書いても undefined になります。もう一つ大事なのは、渡された値がビルド時に文字列として埋め込まれる点です。つまり配信された JavaScript を開けば誰でも読めます。APIキーやデータベースのパスワードをここに置いてはいけません([[シークレット管理]])。.env を書き換えたあとに開発サーバーの再起動が要るのも、埋め込み型だからです。
public/ のファイルは加工されない — コードから import した画像やCSSはファイル名にハッシュが付き、内容が変わったときだけ再取得されます([[HTTPキャッシュ]])。一方 public/ の中身は名前そのままで dist/ へコピーされるだけです。「差し替えたのに古い画像が表示される」の多くはこの違いが原因です。
ここから先を選ぶ地図
Vite は単体で完結する道具ではなく、「何を変換し、何の上で動き、何を作るか」の交差点にあります。近い群から選んでください。
変換の中身を知る
Vite が裏でやっていることを分解すると、[[ESモジュールとバンドラ]] による依存の解決とバンドル、[[トランスパイルとポリフィル]] による新しい記法の変換に行き着きます。型を書くなら [[TypeScript]] ですが、その型を最後に検査するのは Vite ではありません。「設定なしで動く」の中身が見えていると、動かなくなったときに原因を切り分けられます。
この上で何を作るか
Vite はUIの作り方そのものは決めません。[[React]] と [[Vue.js]] はどちらも公式プラグインで数秒で始められます(Vite は Vue の作者が開発したツールです)。ルーティングやデータ取得まで枠組み側に決めてほしくなったら、[[フレームワーク]] とライブラリの違いを踏まえて比較します。
見た目をどう書くか
スタイルの流儀は選べて、どれも追加設定はほとんど要りません。ユーティリティクラスで組み立てる [[Tailwind CSS]] は公式プラグインで統合でき、変数やネストでCSSを拡張する [[CSSプリプロセッサ(Sass)]] は npm install -D sass するだけで .scss が通ります。
動かす土台と配る先
Vite 自身は [[Node.js]] の上で動くプログラムで、導入もプラグイン追加も [[npmとパッケージ管理]] を通します。npm run build が出力する dist/ は静的ファイルの集まりなので、[[CI/CD]] で「ビルドして置く」だけの自動化に載せやすい形です。出力サイズや読み込み順が気になり始めたら [[Webパフォーマンス最適化]] へ進みます。
では「置く」先はどこか、というところでつまずきがちです。dist/ に並ぶのは HTML・CSS・JS・画像(ブラウザがそのまま読める静的ファイル)であって、サーバー上で動き続けるプログラムではありません。だから用意すべきなのは「アプリを実行するサーバー」ではなく、ファイルを置いて配る場所です。開発中に動いていた npm run dev のサーバーは本番には出ていきません。ただし、SSR(サーバー側でHTMLを組み立てる方式)を前提にした [[フレームワーク]] を載せる場合は話が変わり、リクエストのたびにコードを実行できる環境が別に必要になります。
置き場所の選択肢と、ドメイン取得からファイル配置までの流れは [[ホスティングとレンタルサーバー]] にまとまっています。そのうえで、置いた静的ファイルを世界中の拠点から配って距離そのものを縮めるのが [[CDN]] の役割で、近年はホスティングそのものをCDN上で行うサービスも一般的です。
なお、先に触れたハッシュ付きのファイル名は、置いたあとにも効いてきます。「差し替えたのに古いものが配られる」を防ぐ定番の手当てで、ヘッダによる指定の書き方は [[HTTPキャッシュ]]、配信拠点側での効き方は [[CDN]] が扱っています。
品質を同じ設定で守る
[[自動テスト]] のランナー Vitest は、Vite の設定と変換をそのまま共有します。パスのエイリアスや環境変数をテスト用に書き直さなくてよいため、「アプリは動くのにテストだけモジュールを解決できない」という消耗が起きにくくなります。
関連技術とのつながり
- [[React]] — 公式プラグインで開発環境を数秒で用意できる
- [[TypeScript]] — 変換を内蔵しており設定なしで書ける
- [[Tailwind CSS]] — 公式Viteプラグインで統合
- [[自動テスト]] — 同じ設定を共有できるテストランナー Vitest がある
Q: Viteの開発サーバーが、大きなプロジェクトでも速く起動できる理由はどれ?
- [x] アプリ全体をまとめず、ブラウザが要求したファイルだけをその場で変換するから
- [ ] ソースコードを機械語にコンパイルしてから配信するから
- [ ] すべての画面をあらかじめ画像として書き出しておくから
解説: 開発中はES Modulesをそのまま配り、必要になったファイルだけを変換します。数が多い依存ライブラリだけは初回に事前バンドルしておきます。
Q: `import.meta.env.VITE_API_URL` のような値を扱うときの注意として正しいのはどれ?
- [ ] 値は実行のたびにサーバーへ問い合わせるため通信が増える
- [x] 値はビルド時に埋め込まれるため、配信されたJavaScriptから誰でも読める
- [ ] `VITE_` を付けない変数のほうが安全にブラウザへ渡せる
解説: ブラウザ側へ渡るのは`VITE_`で始まる変数だけで、その値はビルド時に文字列として埋め込まれます。APIキーなどの秘密は置けません。
Q: `vite build` と型チェックの関係として正しいのはどれ?
- [x] Viteは型注釈を取り除くだけなので、型エラーが残っていてもビルドは成功しうる
- [ ] 型エラーが1つでもあればViteが必ずビルドを中断する
- [ ] Viteは型チェック専用のツールで、バンドルは行わない
解説: 型が正しいかの検査はViteの担当ではありません。だから多くのプロジェクトは`tsc -b && vite build`のように型チェックを別に走らせます。