生产环境下Vite WebSocket连接丢失问题求助
解决Vite SSR Docker环境下WebSocket连接失败问题
核心问题分析
你的报错源于生产/非dev:client模式下,客户端代码残留了Vite HMR的连接逻辑,导致浏览器反复尝试连接WebSocket端口24678,但服务器端的网络配置或构建流程未匹配该需求;或是dev:server模式下HMR的客户端连接地址配置错误。
解决方案1:生产环境彻底禁用HMR
生产环境(serve命令)不需要HMR,需确保构建的客户端代码完全剔除HMR相关逻辑:
修改Vite配置,按环境控制HMR开关
更新vite.config.ts,仅在非生产环境启用HMR:import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; const isProd = process.env.NODE_ENV === "production"; const PORT = process.env.VITE_PORT ? parseInt(process.env.VITE_PORT) : 3000; export default defineConfig({ plugins: [react()], server: { port: PORT, watch: { usePolling: true, }, hmr: { enabled: !isProd, // 生产环境直接禁用HMR host: "0.0.0.0", // 允许容器外访问HMR(仅开发环境生效) }, }, build: { minify: false, }, define: { "import.meta.env": JSON.stringify(process.env), }, });构建时强制设置生产环境变量
修改package.json的build:client脚本,添加环境变量确保构建产物为生产版本:"build:client": "cross-env NODE_ENV=production vite build --outDir dist/client --ssrManifest",此操作会让Vite自动剔除HMR相关代码,避免浏览器发起无效的WebSocket连接。
解决方案2:dev:server模式下正确配置HMR连接
如果需要在dev:server模式下保留HMR功能,需确保客户端能正确连接容器内的HMR服务:
统一HMR端口到应用端口
在vite.config.ts的server.hmr中设置clientPort为应用端口(3000),无需额外开放24678端口:hmr: { enabled: true, host: "0.0.0.0", clientPort: 3000, // 和应用端口一致,减少端口配置成本 },Nginx反向代理WebSocket请求
更新Nginx配置,确保WebSocket升级请求被正确代理到容器:server { listen 80; server_name example; location / { proxy_pass http://localhost:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # 处理WebSocket协议升级 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } }检查服务器网络配置
- 确认Docker容器已映射3000端口:
ports: ["3000:3000"] - 防火墙开放3000端口:
sudo ufw allow 3000 - 用
netstat -tulpn | grep 3000确认端口未被其他进程占用
- 确认Docker容器已映射3000端口:
解决方案3:SSR渲染时动态注入HMR脚本
如果是SSR应用,需确保仅在开发环境注入Vite客户端脚本:
修改entryServer.tsx,根据环境判断是否添加HMR相关脚本:
import { renderToString } from 'react-dom/server'; import App from './App'; export async function render() { const appHtml = renderToString(<App />); let viteScript = ''; // 仅开发环境注入Vite客户端脚本 if (process.env.NODE_ENV !== 'production') { const vite = await import('vite'); const devServer = await vite.createServer({ server: { middlewareMode: true }, }); viteScript = `<script type="module" src="${devServer.resolvedUrls.local[0]}@vite/client"></script>`; } return ` <html> <head> <title>Your App</title> </head> <body> <div id="root">${appHtml}</div> ${viteScript} </body> </html> `; }
内容的提问来源于stack exchange,提问作者Louis Eiden
相关产品推荐
相关产品推荐

