第15章:フロント(Vite等)をリバプロ越しに見る🌬️🖥️
15.0 いまの“最新版”ざっくりメモ🗓️✨
- Vite の最新安定は 7.3.1(npm の “Latest” 表示)だよ📦✨ (npm)
- Node は v24 が Active LTS / v25 が Current という並び(2026-02 更新)🟢 (Node.js)
15.1 この章のゴール🎯😺
ブラウザは http://front.localhost だけを見ればOKにする🌈
そして…
- 画面が表示される👀✨
- TS/React を保存したら **勝手に画面が差分更新(HMR)**される🔥
- 「
localhost:5173どれだっけ地獄」から解放😇🎉
15.2 なんで詰まりやすいの?(devサーバーの正体)🧠🔍
Vite の dev サーバーは、ただの静的配信じゃなくて…
- ブラウザにモジュールを配る(変換したりもする)📦
- 変更を検知して、WebSocket で HMR 通知を飛ばす⚡🕸️
つまり リバプロが WebSocket を通せないと HMR が死ぬことがあるよ👻 Vite 公式も「Vite の前にいるリバプロは WebSocket をプロキシできる前提」と書いてる📝 失敗すると「プロキシを迂回して直接 WebSocket 接続」にフォールバックする(=変なエラーが出たり、環境によっては繋がらなくなる)って挙動も明記されてるよ🧯 (vitejs)
一方で Caddy の reverse_proxy は WebSocket 対応が標準なので、基本はうまくいく方向💪🍞 (Caddy Web Server)
15.3 まずは図で理解🗺️✨
イメージはこれ👇(“入口”は Caddy だけ)
- ブラウザ →
front.localhost:80 - Caddy →
frontコンテナの5173に中継 - HMR の WebSocket も **同じ入口(80)**を通って中継される
Browser
├─ http://front.localhost/ (HTTP)
└─ ws://front.localhost/ (HMR WebSocket)
│
▼
[Caddy :80]
│ reverse_proxy
▼
[Vite dev :5173]
15.4 “一番ラクに動く”構成(サブドメイン方式)🚀🏷️
dev サーバー(Vite)を パス配下(例:/app)に押し込むと、HTML/アセット/WS のパスが絡んで難しくなりがち😵💫
ここはまず **サブドメイン方式(front.localhost)**で勝ちにいくよ🎯✨
15.4.1 フォルダ構成(例)📁
reverse-proxy-lab/
├─ compose.yml
├─ Caddyfile
└─ front/
├─ package.json
├─ vite.config.ts
└─ src/...
15.4.2 compose.yml(Caddy + Vite)🐳🧩
ポイントはこれ👇
-
Vite は コンテナ外にポート公開しない(公開は Caddy だけ)🔒
-
Vite は
--host 0.0.0.0(コンテナ外=別コンテナから見えるように)📡- Vite の
server.hostは0.0.0.0/trueで全アドレス待受できるよ、って公式にある📝 (vitejs)
- Vite の
services:
caddy:
image: caddy:2
ports:
- "80:80"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
depends_on:
- front
front:
image: node:24
working_dir: /app
volumes:
- ./front:/app
command: sh -c "npm ci && npm run dev -- --host 0.0.0.0 --port 5173 --strictPort"
15.4.3 Caddyfile(front.localhost → Vite)🍞🚪
front.localhost {
reverse_proxy front:5173
}
これで http://front.localhost にアクセスすると Vite が見えるはず👀✨
15.5 Vite 側の“最低限のつぼ”🧠🔧
✅ (1) front.localhost は基本セーフ
Vite は localhost と .localhost 配下ドメインはデフォルト許可って仕様になってる👍
つまり front.localhost / app1.localhost は、基本そのままで通る可能性が高いよ✨ (vitejs)
✅ (2) それ以外のドメインを使うときは server.allowedHosts
もし dev.myapp.test とか独自ドメイン風にしたら、Host がブロックされることがある😇
そのときは server.allowedHosts に追加する(むやみに true は危険寄り)⚠️ (vitejs)
例(独自ホストを許可したい)👇
// front/vite.config.ts
import { defineConfig } from "vite";
export default defineConfig({
server: {
allowedHosts: ["dev.myapp.test"],
},
});
✅ (3) “保存しても反映されない”は WebSocket じゃなくて監視の問題かも👀
Windows + Docker Desktop(WSL2 backend)系だと、ファイル監視が効かない/鈍いことがある(編集が Windows 側プロセスだと特に)って Vite 公式に注意があるよ📝 (vitejs)
対策の方向性は2つ👇
- できれば プロジェクトを WSL 側のファイルシステムに置く(安定&速い)🚀
- どうしても無理なら polling(ただし CPU は上がりやすい)🔥 (vitejs)
polling 例👇(必要なときだけ!)
import { defineConfig } from "vite";
export default defineConfig({
server: {
watch: {
usePolling: true,
},
},
});
15.6 よくある詰まり辞典📕🧯(症状→原因→直し方)
① 画面は出るけど、HMR が効かない(更新されない)😿
-
原因候補A:WebSocket がプロキシされてない
-
Vite は「リバプロが WebSocket を通す前提」📝 (vitejs)
-
Caddy は基本 WebSocket OK 🍞🕸️ (Caddy Web Server)
-
もし別リバプロ(Traefik/Nginx等)なら WS 設定不足の可能性あり
- Traefik は WebSocket を “out of the box” でサポート🧰 (doc.traefik.io)
-
-
原因候補B:ファイル監視が死んでる(WSL2 系)
- 対策:WSL 側に置く or polling (vitejs)
② ブラウザ Console に「Direct websocket connection fallback…」っぽいのが出る👻
-
意味:HMR の WS がリバプロ経由で繋がらず、迂回して直結しにいった合図
-
直し方:
- リバプロで WebSocket を通す(まずこれ)
- それでも環境的にムリなら、Vite の
server.hmrを調整(次の③) (vitejs)
③ HTTPS 絡みで HMR だけ死ぬ(wss/port がズレる)🔐🫠
たとえば入口が https://front.localhost になったり、443 を使う構成になると、HMR の接続先を明示したくなることがあるよ。
Vite の server.hmr は protocol/host/port/clientPort などを持ってる(公式の型定義も明記)📝 (vitejs)
例:入口が 443 のときに “クライアント側の接続先ポート” を揃える感じ👇
import { defineConfig } from "vite";
export default defineConfig({
server: {
strictPort: true,
hmr: {
protocol: "wss",
clientPort: 443,
},
},
});
15.7 デバッグ最短ルート🕵️♂️⚡
ブラウザで確認(いちばん早い)🧠
-
DevTools → Network → WS
-
ws://front.localhost/...が- Status 101 Switching Protocols なら勝ち🎉
- 失敗してたら、そこにエラー理由が出ること多い👀
Docker 側で確認(入口→中を順番に潰す)🐳
-
Caddy コンテナから Vite が見えてる?
- 「名前解決」と「ポート」が正しいかを確認する感じ
(例:front:5173 に到達できるか)
docker compose exec caddy wget -qO- http://front:5173 | head
15.8 ミニ課題🎒✨
front.localhostで Vite を開いて、src/App.tsxを編集→保存→即反映を確認🔥- わざと Caddyfile のポートを
5174にして 502 を出し、原因をログと構成で特定🧯 dev.myapp.testみたいなホスト名を “あえて” 使って Host ブロックを踏み、server.allowedHostsで直す🍪(仕組み理解用)
15.9 Copilot/Codex に投げると速い“勝ちプロンプト”🤖💨
- 「Caddy で
front.localhostを Vite(5173) に reverse_proxy して、HMR(WebSocket)も通る最小 Caddyfile を書いて」🍞 - 「Docker Compose で “Caddyだけ80公開、Viteは内部のみ” の構成にして。Vite は
--host 0.0.0.0前提」🐳 - 「ブラウザで WS が 101 にならない。想定原因を3つに絞って、確認手順を順番に出して」🕵️♂️
15.10 まとめ✅🎉
- Vite の HMR は WebSocket。ここがリバプロ越しで詰まりポイント👻 (vitejs)
- Caddy は
reverse_proxyが WebSocket 対応で基本ラク🍞 (Caddy Web Server) - Docker で Vite を動かすなら
--host 0.0.0.0が超重要📡 (vitejs) - Windows + WSL2 系で「更新されない」は ファイル監視の問題も疑う👀 (vitejs)
次の章(第16章)で「API を同じドメイン配下に寄せて CORS を減らす🧹✨」に進むと、**“フロントとAPIが同じ入口”**になって気持ちよさが一段上がるよ〜😺🚀