ReactでSPAを新しく作るなら、出発点はViteで決まりです。ただ、2026年10月時点の手順は1年前の解説記事とかなり違います。本番ビルドはRolldownに一本化され、テンプレートのリンタはOxlintになり、TypeScriptは7.0が正式公開された一方でテンプレートは6系に固定されたままです。この記事は、2026年10月20日にVite 8.3.4とReact 19.3.1のプロジェクトを実際に生成・ビルドして確かめた手順と数値で構成しています。
まとめ
- 生成は
npm create vite@latest my-app -- --template react-tsの1コマンドです。Node.jsは20系の20.19.0以上、または22.12.0以上が必要です(21系は対象外)。 - Vite 8はesbuildとRollupの2本立てをやめてRolldownへ一本化しました。最新は8.3.4で、9系はまだ公開されていません。
- パスエイリアスは
resolve.tsconfigPaths: trueと tsconfig のpathsで設定します。指定しなくてもvite buildは通りますが、開発サーバーは解決できずに落ちます。 - テンプレートのTypeScriptは
~6.0.3固定です。今回の生成直後のテンプレートでは、7.0.2への更新で型チェックが約4.9秒から約1.7秒に短縮しましたが、baseUrlは削除され、6系で可能だった非推奨エラーの抑制も効かなくなります。 - create-react-appはReact公式が2025年2月14日に新規開発向けの非推奨を告知済みです。検索流入を重視する公開サイトでは、SSR・SSGを備えたフレームワークを第一候補にし、後からレンダリング基盤を組み込む作業を避けます。
Viteとは|React開発でViteが担う範囲
Vite(公式の発音は「ヴィート」。フランス語で「素早い」)はReactの一部でも代替でもありません。JSXやTypeScriptをブラウザが実行できる形へ変換し、開発中はローカルサーバーとして配信し、公開時には静的ファイルへまとめるビルドツールです。Reactと並べて比べる相手はVueやSvelte、Viteと並べて比べる相手はwebpackやParcel、Rsbuildです。Viteを土台にした別用途の例として、Markdownからスライドを作るSlidevとは?Markdownでスライドを作る手順とPDF出力・公開までの実装ガイド【2026年版】もあります。
開発時のネイティブESMと本番ビルドの分担
開発サーバーは起動時にアプリ全体をまとめません。ブラウザのネイティブESMへソースを渡し、importされたファイルだけをその都度変換します。一方で、数百のモジュールを未加工のまま配信するとリクエスト数が膨らむため、公開用にはバンドルします。生成直後のreact-tsテンプレートを起動したログは次のとおりです。
$ npm run dev
VITE v8.3.4 ready in 1143 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
Vite 8のRolldown一本化と8.3までの変化
Vite 8.0の公式アナウンス(2026年3月12日)は、開発時のesbuildと本番のRollupという2本立てをRust製のRolldownへ統合したと説明し、ビルドは最大10〜30倍速くなるとしています。npmのvite 8.3.4のdependenciesにもrollupとesbuildは無く(esbuildは任意のpeerDependenciesとしてのみ残る)、rolldown(実測で1.2.14)とlightningcssが入っています。
| 項目 | Vite 7 | Vite 8 |
|---|---|---|
| 単一ファイル変換 | esbuild | Rolldown(Oxc) |
| 本番バンドル | Rollup | Rolldown |
| CSS最小化(既定) | esbuild | Lightning CSS |
公式はインストールサイズがVite 7比で約15MB増えると明記しており、react-tsテンプレートの node_modules は実測で83MBでした。マイナー版は8.1.0(6月23日)・8.2.0(7月30日)・8.3.0(9月10日)と続き、8.3.0では使用するtsconfigを固定するトップレベルの tsconfig オプションなどが入りました。GSCでは「vite 9」の検索も出始めていますが、2026年10月20日時点のnpmに9系の公開版は1つもありません。バンドラ単体の位置づけはRollupとツリーシェイキングの仕組み|sideEffects・treeshake設定とnpm導入、Vite 8以降の位置づけとesbuildとは?Go製の高速バンドラの使い方と採用判断を実装目線で解説で扱っています。
Vite + Reactプロジェクトを作成する手順
Node.jsの対応バージョンと要件確認
vite 8.3.4のenginesは ^20.19.0 || >=22.12.0 で、公式ガイドも同じ範囲を挙げています。Node.jsが require(esm) をフラグなしで扱える境界に合わせた値です。npmは既定で engine-strict が無効なので、18系でも EBADENGINE の警告が出るだけでインストールは進み、要件割れには起動やビルドの段階で気づくことになります。Vitest・Oxlintなどを束ねたVite+ 1.0は対応範囲が ^22.18.0 || ^24.11.0 || >=26.0.0 と狭く、23系・25系は対象外です。こちらはVite+とは?vpコマンドの使い方と1.0の中身・既存Vite案件の移行手順を実装目線で解説で扱っています。
$ node -v
v26.5.0
$ npm -v
11.17.0
npm create vite@latestによるreact-tsテンプレートの生成
テンプレート名を渡すと種類の選択を省けます。--template の前の -- は、npmではなくcreate-viteへ引数を渡すための区切りで、これを落とすとテンプレート指定が無視されます。通常のターミナルでは、このあとリンタ(Oxlint/ESLint)と「Install with npm and start now?」の2つを聞かれます。質問をすべて省くなら末尾に --no-interactive を付けます(下のログはこの形で実行)。
$ npm create vite@latest my-app -- --template react-ts --no-interactive
create-vite v9.3.1
◇ Scaffolding project in /private/tmp/vr2/my-app...
└ Done. Now run:
cd my-app
npm install
npm run dev
テンプレートを指定せずに npm create vite@latest だけを打つと、フレームワークでReactを選んだあとに次の選択肢が並びます(create-vite 9.3.1の定義から抜粋)。
| 表示 | 生成されるもの |
|---|---|
| TypeScript | react-tsテンプレート |
| TypeScript + React Compiler | react-compiler-tsテンプレート |
| JavaScript | reactテンプレート |
| JavaScript + React Compiler | react-compilerテンプレート |
| RSC | @vitejs/plugin-rscのstarterを取得 |
| React Router v7 ↗ ほか | 各プロジェクトの生成コマンドへ委譲 |
委譲先はReact Router v7・TanStack Start・TanStack Router・RedwoodSDK・Vikeの5つです。迷ったら「TypeScript」で始めて構いません。
生成されるpackage.jsonとディレクトリ構成
{
"name": "my-app",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "oxlint",
"preview": "vite preview"
},
"dependencies": {
"react": "^19.3.1",
"react-dom": "^19.3.1"
},
"devDependencies": {
"@types/node": "^24.19.2",
"@types/react": "^19.3.0",
"@types/react-dom": "^19.3.0",
"@vitejs/plugin-react": "^6.1.2",
"oxlint": "^1.88.0",
"typescript": "~6.0.3",
"vite": "^8.3.4"
}
}
リンタはESLintではなくOxlintです。ESLintの設定資産を引き継ぐなら生成時に --eslint を付けます(Reactテンプレートのみ有効)。両者の差はOxlintとESLintの違いとは?読み方・速度実測・移行手順とBiomeとの比較【1.88対応】にまとめました。TypeScriptだけがチルダ指定の ~6.0.3 で、npmの最新が7.0.2でも npm install では6.0系しか入りません。macOSのnpm 11.17.0では、viteが依存するfseventsについて npm warn allow-scripts の警告が出ましたが、そのまま開発サーバーもビルドも動きました。
my-app
├── index.html
├── package.json
├── .oxlintrc.json
├── public/
│ ├── favicon.svg
│ └── icons.svg
├── src/
│ ├── App.css
│ ├── App.tsx
│ ├── assets/(hero.png・react.svg・vite.svg)
│ ├── index.css
│ └── main.tsx
├── tsconfig.json
├── tsconfig.app.json
├── tsconfig.node.json
└── vite.config.ts
つまずきやすいのは index.html の位置です。create-react-appでは public/index.html がテンプレート扱いでしたが、Viteではプロジェクト直下の index.html そのものがエントリーで、そこから読む src/main.tsx を起点に依存を解決します。public/ のファイルは変換されず、ビルド時に dist/ 直下へそのままコピーされます。
開発サーバーの起動とポート変更
npm install のあと npm run dev で起動し、停止は Ctrl と C の同時押しです。既定の5173番が埋まっていると次の空きポートへ自動でずれるため、コンソールに出たURLを見て開きます。開始ポートの指定には --port、使用中のときに別番号へずらさず起動を止めるには --port 3000 --strictPort、社内ネットワークの別端末から開くなら --host を渡します。既定ではlocalhostだけで待ち受けます。
$ npm run dev -- --port 3000
$ npm run dev -- --host
「’vite’ は、内部コマンドまたは外部コマンド」と出たときの対処
Viteはグローバルコマンドではなく、プロジェクト内の node_modules/.bin に置かれます。Windowsでこのメッセージが出る原因は、ほぼ次の2つです。
npm installをまだ実行していない(または別のディレクトリで実行した)。node_modulesを消した状態でnpm run devを実行すると、macOSでもsh: vite: command not foundになりました- npmスクリプトを通さず、ターミナルで直接
viteと打っている
プロジェクトのディレクトリへ cd し、npm install を済ませてから npm run dev か npx vite で起動してください。npm install -g vite でグローバルに入れる対処は、プロジェクトごとに異なるViteの版と食い違うので勧めません。
create-react-appからViteへの移行手順
create-react-appが非推奨になった経緯
React公式ブログは2025年2月14日のSunsetting Create React Appで、新規アプリでのcreate-react-appの非推奨を告知し、既存アプリにはフレームワークか、Vite・Parcel・Rsbuildへの移行を勧めました。公式が挙げた理由は、実運用向けの制約を解消するにはフレームワークへ発展させる必要がある一方、活動中のメンテナーがおらず、既存のフレームワークがすでに問題を解決していることです。ビルド処理を担う react-scripts の最新は今も2022年4月公開の5.0.1で、4年以上リリースがありません。新規案件で選ぶ理由はありません。
react-scriptsからViteへ移す書き換え箇所
public/index.htmlをプロジェクト直下へ移し、%PUBLIC_URL%を削ってsrc/main.tsxを読むscript type="module"を足すprocess.env.REACT_APP_XXXをimport.meta.env.VITE_XXXへ、接頭辞もVITE_へ変える- JSXを含むファイルの拡張子を
.jsから.jsx(TypeScriptなら.tsx)へ改める - npm scriptsの
react-scripts start/buildをvite/vite buildへ置き換える - Jestのテストを残すか、Vitestへ移す
詰まりやすいのは拡張子と環境変数です。create-react-appは .js のままJSXを解釈していたので、そのまま持ち込むとパースエラーになります。環境変数は接頭辞を変えないとクライアントへ渡らず、値は undefined になります。未定義値の参照だけでは例外になりませんが、その後の処理によっては実行時エラーや誤った通信先へのアクセスにつながります。テストの移し先はVitestの使い方と書き方:読み方・設定からReact Testing Libraryのコンポーネントテストまで【Vitest 5対応】、Vitest 4から上げる場合の差分はVitest 5移行ガイド:4からの破壊的変更と落ちるテストの直し方【2026年10月時点】が対応します。
vite.config.tsとパスエイリアスの設定
vite.config.tsの最小構成とReact Compilerの有効化
生成直後の vite.config.ts はReactプラグインを1つ登録するだけです。このファイルはNode.js側で実行され、ブラウザには届きません。
import react from '@vitejs/plugin-react'
import { defineConfig } from 'vite'
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
})
React Compilerを有効にする方法は、2026年10月時点で2つあります。react-compiler-tsテンプレートが生成するのはBabel経由の書き方で、@rolldown/plugin-babel と babel-plugin-react-compiler を組み合わせます。もう1つは@vitejs/plugin-react 6.1.0(2026年8月19日)で入った実験的なネイティブ版で、Rust移植の oxc-transform-react(6.1.2では0.152以上)を入れて compiler: true を渡します。
// npm install -D oxc-transform-react
import react from '@vitejs/plugin-react'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [react({ compiler: true })],
})
この設定でテンプレートを vite build --minify false したところ、App コンポーネントが (0, import_compiler_runtime.c)(24) で24個のキャッシュ枠を持つ形に変換されていました。ただ、READMEが「experimental」と明記している段階なので、本番で使うなら当面はBabel経由が無難です。自動メモ化の仕組みはReact Compilerとは?自動メモ化の仕組みと導入方法・useMemoとの違いを解説、プラグイン側の変更点は@vitejs/plugin-react とは?v6(Vite 8・Babel廃止)の導入設定と plugin-react-swc との違い【2026年最新】で扱っています。
resolve.tsconfigPathsによるパスエイリアスの一元管理
../../components を @/components と書くパスエイリアスは、型の解決をTypeScriptが、実行時の解決をViteが別々に行います。以前は両方に同じ対応表を書く必要がありましたが、Vite 8には tsconfig の paths をViteに読ませる resolve.tsconfigPaths があり、8.2.0で実験扱いも外れました。設定は次の2か所です。
// vite.config.ts
export default defineConfig({
plugins: [react()],
resolve: { tsconfigPaths: true },
})
// tsconfig.app.json の compilerOptions に1行だけ足す(生成された既定行は消さない)
"paths": { "@/*": ["./src/*"] }
注意したいのは、公式ドキュメント上の既定値が false なのに、8.3.4では指定しなくても vite build が paths を解決して成功してしまう点です。同じ状態で npm run dev を開くと、開発サーバーだけが次のエラーで止まりました。tsconfigから paths を消すとbuildも「Rolldown failed to resolve import」で落ちるので、build側は暗黙にtsconfigを読んでいます。ビルドが通ったことを設定済みの根拠にせず、tsconfigPaths: true を明示してください。
[vite] Failed to resolve import "@/index.css" from "src/main.tsx". Does the file exist?
tsconfig側で baseUrl を書く古い手順は、TypeScript 6.0.3では error TS5101: Option 'baseUrl' is deprecated でビルドが止まります。メッセージが勧める "ignoreDeprecations": "6.0" で黙らせても、7.0.2では error TS5102: Option 'baseUrl' has been removed に変わり、もう回避できません。paths の値はtsconfigファイルからの相対パスで書くのが正解です。CSSやSassの @import でエイリアスを使う場合は、tsconfigの include に src/**/*.css のような拡張子付きの指定が要ります(Lessは非対応)。
TypeScript構成|tsconfigの3分割とTypeScript 7への切り替え
tsconfigの3分割と既定オプション
ルートの tsconfig.json は参照を並べるだけで、src 配下は tsconfig.app.json、vite.config.ts は tsconfig.node.json が担当します。ブラウザとNode.jsで要る型定義が違うため、分けておくと設定ファイルでNode.jsのAPIを使ってもアプリ側の型が汚れません。buildスクリプトが tsc -b(プロジェクト参照モード)なのはこの分割のためです。
| オプション(tsconfig.app.json) | 既定値 | 影響 |
|---|---|---|
| target | es2023 | TS側の言語設定(Viteの出力対象は別設定) |
| moduleResolution | bundler | バンドラ前提の解決 |
| types | [“vite/client”] | 画像・CSSのimport型 |
| verbatimModuleSyntax | true | 型のimportに import type が必須 |
| erasableSyntaxOnly | true | enumなどを禁止 |
既存コードを持ち込むときの最初の関門は後ろの2つです。erasableSyntaxOnly は、enumやコンストラクタ引数のプロパティ宣言のように「型を消すだけでは変換できない」構文をエラーにします。types の行を消すと画像やCSSのimportが TS2307 と TS2882 で落ちるので、tsconfigを他の記事の抜粋で丸ごと置き換えないでください。
TypeScript 7.0.2へ上げたときの型チェック時間
Go移植版のTypeScript 7.0.2(2026年7月8日公開)がnpmのlatestですが、create-vite 9.3.1のテンプレートはまだ6.0.3を入れます。生成直後のプロジェクトで npm i -D typescript@latest を実行して比べると、テンプレートのままなら7.0.2でも npm run build は通り、型チェックの時間は約3分の1になりました。
| npx tsc -b –force(3回) | 実時間 |
|---|---|
| TypeScript 6.0.3 | 4.88〜4.96秒 |
| TypeScript 7.0.2 | 1.66〜1.73秒 |
計測はIntel Core i9-9880H、npxの起動時間を含む値です。生成直後の npm run build 全体は5.79秒で、そのうちViteのバンドルは0.49秒でした。待ち時間の大半は型チェック側なので、CIの時間を縮めたいならViteより先にTypeScriptの版を見直す方が効きます。上げる前に baseUrl が残っていないことと、周辺ツールの対応を確認してください。TypeScript 7.0の公式発表によると、新しいコンパイラAPIは7.1で提供される予定で、それまでtypescript-eslintのようにAPIを使うツールは6.0との併用(npmのエイリアスで両方を入れる)が推奨されています。--eslint 付きで生成した構成は特に注意が要ります。7.0の仕組みはTypeScript 7.0とは?Goネイティブ移植で型チェックを約10倍速くする仕組みを解説で扱っています。
本番ビルドとプレビュー・デプロイの手順
npm run build は tsc -b && vite build なので、型エラーがあればバンドル前に止まります。成果物は dist/ に出力されます。
$ npm run build(出力は抜粋)
vite v8.3.4 building client environment for production...
✓ 20 modules transformed.
dist/index.html 0.45 kB │ gzip: 0.29 kB
dist/assets/index-D64VDMd1.css 4.10 kB │ gzip: 1.47 kB
dist/assets/index-Cl6Bt99l.js 222.45 kB │ gzip: 69.28 kB
✓ built in 492ms
生成直後のJavaScriptは222.45kB(gzip後69.28kB)で、Vite 8.2.1とReact 19.2.8で同じ手順を踏んだ8月の193.27kBより約29kB増えています。同じVite 8.3.4のままReactだけ19.2.8へ戻すと193.22kBに戻るので、増分はReact側です。React 19.3.0(2026年9月9日)では <ViewTransition /> などが追加されました。バンドルサイズの予算をCIで監視しているなら、Reactのマイナー更新でも差分と読み込み性能を確認し、増加を許容できると判断した場合に閾値を見直してください。
確認は npm run preview で、ビルド成果物を既定の4173番ポートでローカル配信します。公式CLIガイドは本番サーバーとして使わないよう明記しており、配信先のヘッダーやキャッシュ設定までは再現しません。ドメイン直下ではなくサブディレクトリに置くなら base: '/app/' の指定が必須で、忘れるとHTMLがルート起点でJavaScriptを読みにいき、画面が真っ白になります。クライアントサイドルーティングを使う場合は、存在しないパスへのリクエストを index.html へ返すフォールバックを配信側に入れます。既存のPHPアプリへ組み込む形なら、Laravel Viteとは?使い方・@viteの書き方と本番ビルドの落とし穴【Laravel 13実測】のマニフェスト連携が参考になります。
Vite + Reactが向かない場面とRSCという中間の選択肢
Viteが提供するのはビルドと開発サーバーで、ルーティングとデータ取得は含まれません。SSRも低レベルのAPIがあるだけです。次に当てはまるなら、Vite + Reactで組み始めるべきではありません。
- JavaScriptの実行を待たずに、初期HTMLへ本文や共有用のメタ情報を含めたい(GoogleはJavaScriptをレンダリングしますが、すべてのクローラーが同じように動くわけではありません)
- 認証状態で出し分けるネストしたルーティングが多い
- 画像最適化・キャッシュ制御・APIルートまで枠組みに任せたい
判断をほぼ決めるのは1つ目です。公開ページの検索流入が事業に効くなら、SSR・SSGを備えたフレームワークを最初に選びます。後からレンダリング基盤を追加する設計・実装を減らせるためです。Next.jsの現在のビルド基盤はTurbopackとは:Next.js 16で既定になったRust製バンドラの設定と移行判断、Vite上で動くフルスタック構成はTanStack Startとは?フルスタックReactフレームワークの特徴・使い方・デプロイ【2026年版】にまとめています。
ただし「サーバーを持ちたくないからVite + React」という理由なら、2026年は中間の選択肢があります。create-viteのメニューにある「RSC」は @vitejs/plugin-rsc(npmの最新は0.5.38)のstarterで、React Server ComponentsをVite上で動かします。この上に作られたFUNSTACK Static(1.3.2)は、READMEで「No server runs」とうたい、静的ファイルとして配信しながらRSCを使える構成です。どちらも0.x系や登場1年未満の段階なので、業務の主系にすぐ据えるより、バンドルを削りたい画面で試すのが現実的です。
逆にVite + Reactがそのまま噛み合うのは、認証の内側で動く管理画面や社内ツール、既存の業務システムの画面だけをリッチにしたいケースです。SEOが要らない領域では、フレームワークの規約に縛られない身軽さが利点になります。こうした画面の作り直しを含む基幹システム開発も弊社で支援しています。SPAのルーティングを足すならTanStack Routerとは?型安全ルーティングの特徴・導入手順とReact Routerとの違いが次の一歩です。
よくある質問
ReactのViteの読み方は?
「ヴィート」です。英語の公式ガイドは「veet」のように、日本語版は「ヴィート」のように発音すると書いており、フランス語で「素早い」を意味する単語です。「バイト」「ビーテ」とは読みません。
ViteとReactの違いは何ですか?
役割が違うので、どちらか一方を選ぶ関係ではありません。Reactは画面を組み立てるUIライブラリで、Viteはそのコードを変換・配信・バンドルするビルドツールです。起動やビルドが遅いという不満はVite側の設定で、再レンダリングが重いという不満はReact側のコードで解く問題です。
Create React Appはなぜ非推奨になったのですか?
React公式が2025年2月14日の記事で、新規アプリ向けの非推奨を告知したためです。公式は、実運用向けの制約を解消するにはフレームワーク化が必要な一方、活動中のメンテナーがおらず、既存フレームワークがすでに解決策を提供していると説明しており、移行先としてフレームワーク、またはVite・Parcel・Rsbuildを挙げています。
Vite 9はもう出ていますか?
2026年10月20日時点のnpmに、Vite 9系の公開版はありません。最新は8.3.4(2026年10月8日)です。ベータ版として出ているのも8.3.0-beta.1までなので、新規プロジェクトは8系で始めて問題ありません。
すでにあるディレクトリの中に直接プロジェクトを作れますか?
プロジェクト名の代わりにピリオドを渡すと、カレントディレクトリ直下に展開されます。Gitリポジトリを先に作ってある場合に使います。ディレクトリが空でないときは確認を求められるので、既存ファイルを消したくなければそこで中止してください。
$ npm create vite@latest . -- --template react-ts