import { defineConfig, loadEnv } from 'vite'; import react from '@vitejs/plugin-react'; import path from 'path'; import fs from 'fs'; // 加载环境变量(Vite 不会自动在配置文件中加载 .env) const env = loadEnv(process.env.NODE_ENV || 'development', process.cwd(), ''); const normalizeBasePath = (value?: string): string => { if (!value) { return '/'; } let normalized = value.trim(); if (!normalized.startsWith('/')) { normalized = `/${normalized}`; } if (!normalized.endsWith('/')) { normalized = `${normalized}/`; } return normalized.replace(/\/{2,}/g, '/'); }; // 后端 API 地址配置(用于代理) // 从 WebSocket URL 推导后端地址,或使用环境变量直接指定 const getBackendUrl = (): string => { // 优先使用环境变量指定的后端地址 if (env.VITE_API_BASE_URL) { return env.VITE_API_BASE_URL; } // 从 WebSocket URL 推导 const wsUrl = env.VITE_WS_URL || 'ws://localhost:8000/ws'; const backendUrl = wsUrl .replace(/^wss:\/\//, 'https://') .replace(/^ws:\/\//, 'http://') .replace(/\/ws$/, ''); return backendUrl; }; const backendUrl = getBackendUrl(); const appBasePath = normalizeBasePath(env.VITE_APP_BASE_PATH); console.log('🔗 后端 API 代理配置:'); console.log(` 目标地址: ${backendUrl}`); console.log(` 代理路径: /api -> ${backendUrl}/api`); console.log(`🌐 前端基础路径(base): ${appBasePath}`); // SSL证书配置 // HTTPS开关:通过环境变量 VITE_ENABLE_HTTPS 控制(true/false) const enableHttps = env.VITE_ENABLE_HTTPS === 'true'; // 优先使用环境变量指定的证书路径(生产环境) const sslKeyPath = env.VITE_SSL_KEYFILE || path.resolve(__dirname, '../ssl/key.pem'); const sslCertPath = env.VITE_SSL_CERTFILE || path.resolve(__dirname, '../ssl/cert.pem'); // 根据开关和证书文件决定HTTPS配置 let httpsConfig: any = false; if (enableHttps) { if (fs.existsSync(sslKeyPath) && fs.existsSync(sslCertPath)) { httpsConfig = { key: fs.readFileSync(sslKeyPath), cert: fs.readFileSync(sslCertPath), }; console.log('✅ HTTPS已启用,使用SSL证书:'); console.log(` 证书: ${sslCertPath}`); console.log(` 私钥: ${sslKeyPath}`); } else { console.log('⚠️ HTTPS已启用但SSL证书不存在,以HTTP模式启动'); console.log(` 证书路径: ${sslCertPath}`); console.log(` 私钥路径: ${sslKeyPath}`); } } else { console.log('ℹ️ HTTPS已禁用(VITE_ENABLE_HTTPS=false),以HTTP模式启动'); } export default defineConfig({ base: appBasePath, plugins: [react()], resolve: { alias: { '@': path.resolve(__dirname, './src'), }, }, assetsInclude: ['**/*.GIF'], server: { port: 3000, host: '0.0.0.0', // 允许外部访问 https: httpsConfig, // 代理配置:将 /api 请求代理到后端服务器 // 这样可以避免跨域和证书问题(Safari 对自签名证书的跨域请求很严格) proxy: { '/api': { target: backendUrl, changeOrigin: true, secure: false, // 允许自签名证书 // 如果需要 WebSocket 代理,取消下面的注释 // ws: true, }, }, }, });