You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vite应用遇“WebSocket连接建立前已关闭”错误,调试无果求解决方案

解决Vite中Socket.io连接报错“WebSocket is closed before the connection is established”

问题重现

运行Vite React应用时,控制台持续输出错误:WebSocket is closed before the connection is established,尝试常规方法后仍无法解决,连接初始化代码如下:

import useSocket from "@/utils/socket";
import { createContext, useCallback, useEffect, useRef, useState } from "react";
import { AppContext } from "./context";
import { useCookies } from "react-cookie";
import { io } from "socket.io-client";
import { Socket } from "socket.io-client";
import { DefaultEventsMap } from "socket.io";


export const ContextProvider = ({children}) => {
    
    const [cookies] = useCookies(['token'])
    const [isConnected, setIsConnected] = useState(false)
    const [socket, setSocket] = useState<Socket<DefaultEventsMap, DefaultEventsMap> | null>(null)


    const [onlineCount, setOnlineCount] = useState(0)

     useEffect(() => {
        let newSocket: Socket<DefaultEventsMap, DefaultEventsMap> | null = null;

        if (cookies.token) {
            console.log(cookies.token)
            newSocket = io({
                auth: cookies.token,
                reconnection: true, // Enables automatic reconnection
                reconnectionAttempts: 5, // Number of retry attempts
                reconnectionDelay: 1000, 
            });

            console.log("connect")
            newSocket.on("connect", () => {
                console.log("Socket connected")
                setIsConnected(true)
                setSocket(newSocket)
            })
            console.log("connected")

            newSocket.on("connect_error", (error) => {
                console.error("Connection Error:", error.message);
            });

            newSocket.on('disconnect', (reason) => {
                console.log("Socket disconnected", reason)
                setIsConnected(false)
                setSocket(null)
            });

            return () => {
                if(newSocket) {
                    newSocket.disconnect()
                }
                
            }
        }
    }, [cookies.token])

    

    const contextValue = {socket}

    return (
        <AppContext.Provider value={contextValue}>
            {children}
        </AppContext.Provider>
    )
}

排查与修复方案

1. 明确Socket.io服务端地址

当前代码中io()未传入服务端URL,Socket.io客户端会默认连接当前页面的域名端口,但Vite开发服务器和Socket.io服务端大概率不在同一地址,直接导致连接失败。
修改方式:在io()中传入服务端完整地址,同时修正auth参数格式(服务端通常期望接收对象格式的认证信息):

newSocket = io('http://localhost:3001', { // 替换为你的Socket.io服务端实际地址
    auth: { token: cookies.token },
    reconnection: true,
    reconnectionAttempts: 5,
    reconnectionDelay: 1000,
});

2. 配置Vite开发服务器代理

如果Socket.io服务端和Vite开发服务器跨域,必须在vite.config.ts中配置代理,避免跨域策略阻断WebSocket连接:

export default defineConfig({
  server: {
    proxy: {
      '/socket.io': {
        target: 'http://localhost:3001', // 服务端地址
        ws: true, // 启用WebSocket代理
        changeOrigin: true,
      },
    },
  },
});

配置完成后,客户端可使用相对路径io('/'),由Vite自动转发请求到服务端。

3. 优化Socket实例管理

原代码用useState保存socket实例,连接重连时可能触发不必要的状态更新。改用useRef保存实例,避免重复创建和状态异常:

const socketRef = useRef<Socket<DefaultEventsMap, DefaultEventsMap> | null>(null);

useEffect(() => {
  if (cookies.token) {
    socketRef.current = io('http://localhost:3001', {
      auth: { token: cookies.token },
      reconnection: true,
      reconnectionAttempts: 5,
      reconnectionDelay: 1000,
    });

    socketRef.current.on("connect", () => {
      console.log("Socket connected");
      setIsConnected(true);
    });

    socketRef.current.on("connect_error", (error) => {
      console.error("Connection Error:", error.message);
    });

    socketRef.current.on('disconnect', (reason) => {
      console.log("Socket disconnected", reason);
      setIsConnected(false);
    });

    return () => {
      socketRef.current?.disconnect();
      socketRef.current = null;
    };
  }
}, [cookies.token]);

// 上下文值使用ref的current实例
const contextValue = { socket: socketRef.current };

4. 检查服务端认证逻辑

服务端若无法正确解析客户端传入的token,会直接关闭连接触发该错误。在服务端添加日志确认认证信息接收情况:

// 服务端示例代码
io.on('connection', (socket) => {
  const token = socket.handshake.auth.token;
  console.log('Received token:', token);
  // 执行token验证逻辑
  if (!validateToken(token)) {
    socket.disconnect(true); // 认证失败强制断开
    return;
  }
  // 后续业务逻辑
});

5. 排查浏览器环境限制

  • 确保应用通过http://或https://协议访问,避免file://协议下的WebSocket限制;
  • 暂时禁用浏览器的广告拦截、隐私保护类插件,排查是否有插件阻断了WebSocket连接。

内容的提问来源于stack exchange,提问作者Josh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 06:55:18