React+Vite通过Express代理实现Socket.io连接的问题排查
解决React+Vite代理Socket.io连接失败的问题
问题根源
你遇到的核心问题是Socket.io的请求路径与Vite代理规则不匹配:
- Socket.io客户端发起两类请求:WebSocket握手请求和HTTP轮询请求,默认路径都带有
/socket.io后缀 - 你的Vite代理规则会重写路径,导致轮询请求转发到后端后变成根路径请求(
/?EIO=4...),而后端Socket.io默认只处理/socket.io路径的请求,因此返回404 - 直接使用完整URL连接时,请求路径完全匹配后端Socket.io的监听规则,所以能正常连接
解决方案
方案一:规范路径匹配(推荐)
保留Socket.io默认的/socket.io路径,通过调整客户端和代理规则实现正确转发:
- React客户端配置
指定Socket.io的请求路径,确保所有请求都以/ws/socket.io开头:
import { io } from 'socket.io-client'; export const socket = io('/ws', { autoConnect: false, withCredentials: true, path: '/socket.io' // 关键:让Socket.io请求路径为/ws/socket.io });
- Vite代理配置
代理/ws开头的所有请求,重写时去掉/ws前缀,转发到后端的/socket.io路径:
import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; export default defineConfig({ server: { host: '0.0.0.0', proxy: { '/ws': { target: 'http://localhost:5002', changeOrigin: true, secure: false, ws: true, rewrite: path => path.replace(/^\/ws/, '') } } }, plugins: [react()] });
- 后端配置(无需修改)
保持现有的Socket.io配置即可,因为后端默认监听/socket.io路径:
const io = new Server(httpServer, { cors: { origin: process.env.CLIENT_URL, credentials: true, }, // path默认就是/socket.io,无需额外配置 });
方案二:调整后端Socket.io监听路径
如果不想修改客户端配置,可以让后端Socket.io直接监听代理路径:
- 后端配置
修改Socket.io的path为/ws:
const io = new Server(httpServer, { cors: { origin: process.env.CLIENT_URL, credentials: true, }, path: '/ws' // 让Socket.io监听/ws路径 });
- Vite代理配置
去掉路径重写规则,直接转发/ws开头的请求:
import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; export default defineConfig({ server: { host: '0.0.0.0', proxy: { '/ws': { target: 'http://localhost:5002', changeOrigin: true, secure: false, ws: true, // 移除rewrite配置 } } }, plugins: [react()] });
- 客户端配置(无需修改)
保持你原来的客户端代码即可:
import { io } from 'socket.io-client'; export const socket = io('/ws', { autoConnect: false, withCredentials: true, });
验证
配置完成后,启动客户端和后端:
- 检查浏览器控制台是否有连接成功的日志
- 后端控制台应该能收到
connection事件的触发日志
内容的提问来源于stack exchange,提问作者Findingoak2
相关产品推荐
相关产品推荐

