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

在SvelteKit中用ws包搭建WebSocket服务器及解决热重载端口冲突

在SvelteKit中使用ws模块搭建无端口冲突的WebSocket服务器

问题原因

你遇到的端口占用问题,本质是两个错误操作导致:

  • 最初的代码单独启动了监听8080端口的WebSocket服务器,Vite热更新时未自动关闭旧的WS服务器实例,新实例启动时端口被占用。
  • 后续复用Vite HTTP服务器的尝试中,额外调用了httpServer.listen(8080)——但Vite已经启动了自身的HTTP服务器并监听默认端口(如5173),重复调用listen会触发端口冲突。

Socket.io示例正常的原因

Socket.io的示例之所以无冲突,核心是完全复用Vite已启动的HTTP服务器:

  • 它没有单独创建新服务器或调用listen,仅将Socket.io挂载到Vite的server.httpServer上。
  • Vite热更新时会自动管理内置HTTP服务器的生命周期,Socket.io会随服务器重启重新挂载,不会残留旧实例占用端口。

可行的ws模块实现方案

要解决问题,需做到两点:复用Vite的HTTP服务器、管理WS服务器生命周期避免残留。以下是修正后的代码:

import type { UserConfig } from 'vite';
import { sveltekit } from '@sveltejs/kit/vite';
import { WebSocketServer } from "ws";

const webSocketServer = {
    name: "webSocketServer",
    configureServer: (server: any) => {
        const httpServer = server.httpServer;
        // 使用noServer模式,不单独启动服务器
        const wss = new WebSocketServer({ noServer: true });

        wss.on("connection", (socket, request) => {
            console.log('客户端已连接');
            socket.on("message", (data, isBinary) => {
                console.log(`收到消息: ${data.toString()}`);
                socket.send(`服务器收到: ${data.toString()}`);
            });
            
            socket.send("欢迎连接WebSocket服务器");

            socket.on("close", () => {
                console.log('客户端已断开');
            });
        });

        // 绑定HTTP服务器的upgrade事件,处理WebSocket升级请求
        httpServer.on("upgrade", (request: any, socket: any, head: any) => {
            wss.handleUpgrade(request, socket, head, (ws) => {
                wss.emit("connection", ws, request);
            });
        });

        // 监听Vite服务器关闭事件,手动关闭WS服务器,避免热更新残留
        server.httpServer.on('close', () => {
            wss.close();
        });
    }
}

const config: UserConfig = {
    plugins: [sveltekit(), webSocketServer]
};

export default config;

前端连接方式

因为复用了Vite开发服务器的端口(默认5173),前端+page.svelte的连接代码如下:

<script>
    let socket;

    function connect() {
        socket = new WebSocket(`ws://${window.location.host}`);
        
        socket.onopen = () => {
            console.log('连接服务器成功');
            socket.send('Hello 服务器');
        };

        socket.onmessage = (event) => {
            console.log('收到服务器消息:', event.data);
        };

        socket.onclose = () => {
            console.log('与服务器断开连接');
        };
    }

    function sendMessage() {
        if (socket && socket.readyState === WebSocket.OPEN) {
            socket.send('测试消息');
        }
    }
</script>

<button on:click={connect}>连接WebSocket</button>
<button on:click={sendMessage}>发送消息</button>

关键说明

  1. noServer模式:ws的noServer: true选项让它依赖已有HTTP服务器处理升级请求,不单独启动新服务器。
  2. 生命周期管理:监听Vite服务器的close事件手动关闭WS服务器,确保热更新时旧实例被销毁,避免资源占用。
  3. 复用端口:直接使用Vite开发服务器的端口,无需额外指定WS端口,彻底避免端口冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 08:30:49