在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>
关键说明
- noServer模式:ws的
noServer: true选项让它依赖已有HTTP服务器处理升级请求,不单独启动新服务器。 - 生命周期管理:监听Vite服务器的
close事件手动关闭WS服务器,确保热更新时旧实例被销毁,避免资源占用。 - 复用端口:直接使用Vite开发服务器的端口,无需额外指定WS端口,彻底避免端口冲突。
内容的提问来源于stack exchange,提问作者OOPS Studio
相关产品推荐
相关产品推荐

