こんにちは!日々のフロントエンド開発、本当にお疲れ様です。
突然ですが、こんな経験はありませんか?
「ローカルでAPIを叩こうとしたらCORS(オリジン間リソース共有)のエラーで弾かれた」
「チームメンバーごとにバックエンドのローカル起動ポートが違っていて、`vite.config.ts` の `server.proxy` の書き換え・コンフリクトで毎回消耗している」
大規模な開発現場になればなるほど、こうした「環境差異による細かなコンフィグの手間」は、エンジニアの創造的な時間を静かに奪っていきます。
今回は、Viteのプロキシ設定を完全に自動化し、「誰がどの環境で立ち上げても、バックエンドの所在を自動検知していい感じにルーティングしてくれる仕組み」 を一緒に作っていきましょう。
これをマスターすれば、毎日のコーディング開始時のストレスが劇的に消え去りますよ。さあ、ワンランク上の開発環境を手に入れに行きましょう!
—
そもそも「ViteのProxyサーバー」とは何をしているのか?
まずは、Viteの裏側で何が起きているのかをすっきりと理解しておきましょう。
モダンなWebフロントエンド開発では、通常、Viteの開発サーバー(`http://localhost:5173` など)を立ち上げてコーディングを行います。一方で、バックエンド(Rails, Laravel, Go, Expressなど)は別のポート(例えば `http://localhost:3000` や `8080`)で動いています。
ここでブラウザから直接バックエンドへリクエストを送ると、セキュリティ機構である CORS に引っかかります。
[ ブラウザ ] — (CORSの壁) –> [ バックエンド (ポート3000) ]
そこで登場するのが、Viteの `server.proxy` 機能です。
Viteの開発サーバー自身が「リバースプロキシ」として振る舞い、ブラウザからのリクエストを一度受け取って、裏側でこっそりバックエンドへ転送(プロキシ)します。
[ ブラウザ ] —> [ Viteサーバー (ポート5173) ] — (サーバー間通信・CORSなし) –> [ バックエンド ]
サーバー間の通信にはCORSの概念が存在しないため、ブラウザからは「同一オリジンへのリクエスト」に見せかけつつ、安全かつスムーズにAPI通信ができるというわけです。
—
従来のプロキシ設定が抱える「痛い課題」
通常のViteの設定 (`vite.config.ts`) は、以下のようにハードコーディングされがちです。
// よくあるハードコーディングされた設定
export default defineConfig({
server: {
proxy: {
‘/api’: {
target: ‘http://localhost:3000’, // ここが固定されている!
changeOrigin: true,
},
},
},
})
これの何が問題かと言うと、
1. 担当する機能によって、あるいはマイクロサービスアーキテクチャの場合に、接続先バックエンドが複数(認証系は3001、商品系は3002など)に分かれる。
2. 開発者Aはポート3000、開発者Bは環境の都合でポート8080でバックエンドを動かしたい、といった個人の自由が利かない。
3. ステージング環境やリモートのモックサーバーに向き先を変えるたびに、コンフィグ書き換えとGitのコンフリクトリスクに怯えることになる。
この煩わしさを、「環境変数と動的スクリプト」の力で完全に自動化してしまいましょう。
—
実装:バックエンドAPIを自動検知して動的にプロキシを切り替える仕組み
ここからが本題です。
Viteのコンフィグファイル(`vite.config.ts`)は、ただの静的なJSONではありません。TypeScript(あるいはJavaScript)のコードをそのまま実行できるため、起動時に動的にロジックを組み込むことができます。
今回は、以下の要件を満たすスマートな仕組みを構築します。
- `.env` ファイルや環境変数(`VITE_API_BASE_URL` など)が指定されていれば、それを優先する。
- 指定がない場合は、ローカルの標準的なポートフォリオを走査するか、あるいはプロジェクトの構造に合わせて柔軟にターゲットを決定する。
- 複数のAPIプレフィックス(`/api`, `/auth`, `/ws` など)を一括で、かつ動的にルーティングする。
1. プロジェクト構造の確認
最小限のViteプロジェクトを想定します。
my-app/
┣ node_modules/
┣ src/
┣ .env.development
┣ package.json
┗ vite.config.ts
2. 環境変数の定義 (`.env.development`)
まずは、ベースとなる環境変数を定義します。ここに何も書かれていない場合(あるいはデフォルト値)のフォールバック挙動を、コード側で賢く制御します。
.env.development
明示的にバックエンドの向き先を変えたい場合はここに記述する
未指定の場合は、スクリプト側で自動判定(デフォルト: http://localhost:8080)のフォールバックが走る
VITE_BACKEND_HOST=http://localhost:8080
3. 知的で頑健な `vite.config.ts` の実装
それでは、今回のメインディッシュである `vite.config.ts` を記述します。
コード内のコメントに、アーキテクトとしての設計意図をたっぷりと書き込みましたので、じっくり読み解いてみてください。
import { defineConfig, loadEnv } from ‘vite’
import react from ‘@vitejs/plugin-react’ // Vueの場合は @vitejs/plugin-vue に読み替えてください
export default defineConfig(({ mode }) => {
// 1. 現在のモード(development, production等)に応じた環境変数をロードする
// 3番目の引数を ” にすることで、VITE_ プレフィックス以外の環境変数も取得可能にする
const env = loadEnv(mode, process.cwd(), ”)
// 2. バックエンドのターゲットURLを決定する優先順位ロジック
// 優先順位:
// ① 実行時環境変数 (process.env.API_TARGET)
// ② .envファイルで定義された変数 (env.VITE_BACKEND_HOST)
// ③ どちらもなければデフォルトのローカル開発サーバー (http://localhost:8080)
const targetServer =
process.env.API_TARGET ||
env.VITE_BACKEND_HOST ||
‘http://localhost:8080’
console.log(`[Vite Proxy Setup] 🚀 バックエンドAPIの転送先ターゲット: ${targetServer}`)
return {
plugins: [react()],
server: {
port: 5173, // Viteのフロントエンド起動ポート
host: true, // ネットワーク経由(スマホや別PC)からのアクセスも許可する
proxy: {
// 3. 複数のAPIパスパターンを動的にハンドリングする高度なプロキシ設定
// /api で始まるリクエストはすべてバックエンドへ転送
‘^/api’: {
target: targetServer,
changeOrigin: true, // ホストヘッダーのオリジンをターゲットのそれに書き換える(CORS対策の要)
// 必要に応じてパスの書き換えを行う(例: /api/v1/users -> /v1/users にしたい場合など)
// rewrite: (path) => path.replace(/^\/api/, ”),
// 4. プロキシ先のバックエンドが落ちているときや、通信エラー時のハンドリングをログに出力する
configure: (proxy, _options) => {
proxy.on(‘error’, (err, _req, _res) => {
console.error(‘[Vite Proxy Error] ⚠️ バックエンドとの通信に失敗しました:’, err)
})
proxy.on(‘proxyReq’, (proxyReq, req, _res) => {
// 開発時にどのリクエストがどこに飛ばされているかを可視化するデバッグログ
console.log(`[Vite Proxy] 🔄 リクエスト転送: ${req.method} ${req.url} -> ${targetServer}${req.url}`)
})
},
},
// 5. WebSocketなどのリアルタイム通信が必要なパスも個別に、かつスマートにルーティング
‘^/ws’: {
target: targetServer,
ws: true, // WebSocketのプロキシを有効化する
changeOrigin: true,
},
},
},
}
})
—
動作確認:いざ、プロキシの挙動を体感する!
この設定がどれほどエレガントに動くか、実際に確認してみましょう。
1. 開発サーバーの起動
通常通り、以下のコマンドでViteを起動します。
npm run dev
コンソール(ターミナル)に注目してください。先ほど仕込んだ親切なログが出力されるはずです。
[Vite Proxy Setup] 🚀 バックエンドAPIの転送先ターゲット: http://localhost:8080
VITE v5.0.0 ready in 320 ms
➜ Local: http://localhost:5173/
➜ Network: use –host to expose
➜ press h + enter to show help
2. 環境変数を動的に切り替えてみる
もし別のバックエンド(例: `http://localhost:9000`)へ一時的に切り替えたい場合は、わざわざファイルを書き換える必要はありません。コマンド一発で環境変数を注入して起動できます。
Mac / Linux の場合:
API_TARGET=http://localhost:9000 npm run dev
Windows (PowerShell) の場合:
$env:API_TARGET=”http://localhost:9000″; npm run dev
ターミナルのログを見ると、コードを1文字も書き換えることなく、ターゲットが瞬時に `http://localhost:9000` に切り替わっているのが確認できるはずです。
3. フロントエンドからのフェッチテスト
`src/App.tsx` などから、以下のように `/api/health` などのエンドポイントを叩いてみます。
import { useEffect } from ‘react’
function App() {
useEffect(() => {
fetch(‘/api/health’)
.then((res) => res.json())
.then((data) => console.log(‘APIレスポンス:’, data))
.catch((err) => console.error(‘APIエラー:’, err))
}, [])
return (
Vite Proxy Auto-Configured!
)
}
export default App
ブラウザのコンソールと、Viteを起動しているターミナルを並べて見てください。
ターミナル側に `[Vite Proxy] 🔄 リクエスト転送: GET /api/health -> http://localhost:8080/api/health` というログが流れ、CORSエラーを一切起こすことなく、美しくバックエンドと通信できていることが分かります。
—
先輩エンジニアからの実践的なアドバイス
今回導入した「動的プロキシ設定」は、チーム開発において以下のような計り知れないメリットをもたらします。
1. オンボーディングの摩擦がゼロになる
新しくプロジェクトに参加したメンバーが、複雑な環境構築マニュアルに悩まされることなく、`npm run dev` を叩くだけで即座に開発を始められます。
2. Docker環境やCI/CDとのシームレスな統合
コンテナ環境やリモート開発環境(GitHub CodespacesやGitpodなど)に移行した際も、環境変数(`API_TARGET`)をコンテナの起動引数として渡すだけで、フロントエンドのコードを一切触らずに適応させることができます。
「面倒な設定はコードに語らせ、人間はクリエイティブなコードを書くことに集中する」。これが、プロフェッショナルなDevOps・フロントエンドアーキテクトの流儀です。
ぜひ、あなたのプロジェクトの `vite.config.ts` にもこの仕組みを取り入れて、快適な開発ライフを満喫してください!