import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import fs from 'fs'; const httpsEnv = (process.env.HTTPS || '').toLowerCase(); const useHttps = httpsEnv === 'true' || httpsEnv === '1'; import tsconfigPaths from 'vite-tsconfig-paths' // If custom cert paths are provided via env, use them; otherwise let Vite handle a self-signed cert when true. const httpsOption = useHttps ? (process.env.VITE_HTTPS_KEY && process.env.VITE_HTTPS_CERT ? { key: fs.readFileSync(process.env.VITE_HTTPS_KEY), cert: fs.readFileSync(process.env.VITE_HTTPS_CERT) } : true) : false; // Determine base path from env (PUBLIC_URL or VITE_BASEPATH). Keep a // normalized value with a leading slash and a trailing slash (e.g. // '/ketr.ketran/'), or just '/' when empty/root. This matches how the // built client writes a and avoids dev-server // mismatches that lead to helpful-but-confusing 404 text responses. const rawBase = process.env.PUBLIC_URL || process.env.VITE_BASEPATH || '/'; let normalizedBase = rawBase || '/'; if (normalizedBase.length > 1) { // Ensure leading slash and single trailing slash normalizedBase = normalizedBase.replace(/^\/+/, '/').replace(/\/+$/, '') + '/'; if (!normalizedBase.startsWith('/')) normalizedBase = '/' + normalizedBase; } else { // Root normalizedBase = '/'; } export default defineConfig({ // Base public path when served in dev or production. Allow overriding // via environment variables (PUBLIC_URL or VITE_BASEPATH). base: normalizedBase, plugins: [ react(), tsconfigPaths(), // Dev-only plugin: when the dev server receives requests that are // already prefixed with the base (e.g. /ketr.ketran/assets/...), strip // the prefix so Vite can serve the underlying files from /assets/... { name: 'strip-basepath-for-dev', configureServer(server) { // Only install the middleware when a non-root base is configured if (!normalizedBase || normalizedBase === '/') return; server.middlewares.use((req, res, next) => { try { // Log incoming base-prefixed requests for debugging only. Do NOT // rewrite the URL — Vite is configured with the same `base` so it // expects requests to include the base. Rewriting to remove the // base causes Vite to return an explanatory 404 ("The server is // configured with a public base URL...") for paths like // '/@vite/client'. Let Vite handle the request as-is. if (req.url && req.url.indexOf(normalizedBase) === 0) { if (req.url === normalizedBase) { console.log(`[vite] incoming url (base root): ${req.url} (base ${normalizedBase})`); } else { console.log(`[vite] incoming url: ${req.url} (base ${normalizedBase})`); // If the incoming request is for a public asset (e.g. // '//assets/...'), strip the base so Vite can // serve the static file from '/assets/...'. We only rewrite // asset paths here to avoid interfering with module paths // and HMR endpoints which Vite already serves correctly // when the server `base` is configured. const assetsPrefix = normalizedBase.replace(/\/$/, '') + '/assets/'; if (req.url.indexOf(assetsPrefix) === 0) { const original = req.url; // Preserve the base and change '/assets/' to '/gfx/' so the // dev server serves files from public/gfx which are exposed at // '//gfx/...'. Example: '/ketr.ketran/assets/gfx/x' -> // '/ketr.ketran/gfx/x'. const baseNoTrail = normalizedBase.replace(/\/$/, ''); req.url = req.url.replace(new RegExp('^' + baseNoTrail + '/assets/'), baseNoTrail + '/gfx/'); console.log(`[vite] rewritten asset ${original} -> ${req.url}`); } } } } catch (e) { // ignore and continue } next(); }); } } ], build: { outDir: 'build', }, server: { host: process.env.HOST || '0.0.0.0', port: Number(process.env.PORT) || 3001, https: httpsOption, proxy: { // Support requests that already include the basePath (/ketr.ketran/api) // and requests that use the shorter /api path. Both should be forwarded // to the backend server which serves the API under /ketr.ketran/api. '/ketr.ketran/api': { target: 'http://pok-server:8930', changeOrigin: true, ws: true, secure: false }, '/api': { target: 'http://pok-server:8930', changeOrigin: true, ws: true, secure: false, rewrite: (path) => `/ketr.ketran${path}` } }, // HMR options: advertise the external hostname and port so browsers // accessing via `battle-linux.ketrenos.com` can connect to the websocket. // The certs mounted into the container must be trusted by the browser. hmr: { host: process.env.VITE_HMR_HOST || 'battle-linux.ketrenos.com', port: Number(process.env.VITE_HMR_PORT) || 3001, protocol: process.env.VITE_HMR_PROTOCOL || 'wss' }, } });