From 72ba4d127263af2506da5879bc4cdf6240cc506f Mon Sep 17 00:00:00 2001 From: Daniel Volz Date: Sun, 10 May 2026 20:49:15 +0200 Subject: [PATCH] chore: support proxied frontend dev hosts --- README.md | 8 ++++++++ frontend/vite.config.ts | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/README.md b/README.md index fa620db..fd6b774 100644 --- a/README.md +++ b/README.md @@ -378,6 +378,14 @@ docker compose -p medassist-dev -f docker-compose.dev.yml up - API docs UI: `http://localhost:3000/docs` (when docs are enabled) - OpenAPI JSON: `http://localhost:3000/docs/json` (when docs are enabled) +If you run the frontend dev server behind a reverse proxy or on a remote host, you can optionally set these frontend-only environment variables before starting Vite: + +- `VITE_ALLOWED_HOSTS`: comma-separated hostnames allowed to connect to the dev server; defaults to `localhost,127.0.0.1` +- `VITE_HMR_HOST`: public hostname used for HMR websocket connections +- `VITE_HMR_PROTOCOL`: optional websocket protocol override (`ws` or `wss`) +- `VITE_HMR_CLIENT_PORT`: optional public websocket port exposed to the browser +- `VITE_HMR_PORT`: optional server-side websocket port for the Vite process + Useful local commands: ```bash diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 78752a8..c51644e 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -2,6 +2,24 @@ import { existsSync, readFileSync } from "fs"; import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; +function parseCsvEnv(value: string | undefined, fallback: string[]) { + const entries = value + ?.split(",") + .map((entry) => entry.trim()) + .filter((entry) => entry.length > 0); + + return entries && entries.length > 0 ? entries : fallback; +} + +function parseOptionalPort(value: string | undefined) { + if (!value) { + return undefined; + } + + const parsed = Number.parseInt(value, 10); + return Number.isFinite(parsed) ? parsed : undefined; +} + // Read version from package.json at build time const packageJson = JSON.parse(readFileSync("./package.json", "utf-8")); @@ -9,6 +27,19 @@ const packageJson = JSON.parse(readFileSync("./package.json", "utf-8")); // In Docker, prefer backend-dev to avoid localhost proxy failures. const defaultBackendTarget = existsSync("/.dockerenv") ? "http://backend-dev:3000" : "http://localhost:3000"; const backendTarget = process.env.BACKEND_URL || defaultBackendTarget; +const allowedHosts = parseCsvEnv(process.env.VITE_ALLOWED_HOSTS, ["localhost", "127.0.0.1"]); +const hmrHost = process.env.VITE_HMR_HOST?.trim(); +const hmrProtocol = process.env.VITE_HMR_PROTOCOL === "ws" ? "ws" : process.env.VITE_HMR_PROTOCOL === "wss" ? "wss" : undefined; +const hmrClientPort = parseOptionalPort(process.env.VITE_HMR_CLIENT_PORT); +const hmrPort = parseOptionalPort(process.env.VITE_HMR_PORT); +const hmr = hmrHost + ? { + host: hmrHost, + protocol: hmrProtocol ?? "wss", + clientPort: hmrClientPort ?? (hmrProtocol === "ws" ? 80 : 443), + port: hmrPort ?? 5173, + } + : undefined; export default defineConfig({ plugins: [react()], @@ -19,6 +50,8 @@ export default defineConfig({ server: { port: 5173, strictPort: true, + allowedHosts, + hmr, proxy: { "/api": { target: backendTarget,