如何使用 ws 包在 SvelteKit 内设置 WebSocket 服务器?

OOP*_*dio 4 websocket node.js ws vite sveltekit

我正在尝试创建一个将在 SvelteKit 应用程序中运行的简单 WebSocket 服务器。我在网上找到了这个教程,它展示了如何使用 Socket.io 来完成此操作,但是我想改用该ws模块。

这是vite.config.ts我迄今为止提出的文件:

import type { UserConfig } from 'vite';

import { sveltekit } from '@sveltejs/kit/vite';

import { WebSocketServer } from "ws";

const webSocketServer = {
    name: "webSocketServer",
    configureServer: () => {
        const webSocketServer = new WebSocketServer({
            port: 8080
        });
    
        webSocketServer.on("connection", (socket, request) => {
            socket.on("message", (data, isBinary) => {
                console.log(`Recieved ${data}`);
            });
        
            socket.send("test from server");
        });
    }
}

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

export default config;
Run Code Online (Sandbox Code Playgroud)

我可以从前端(例如,在 中)连接到此 WebSocket 服务器+page.svelte并在它们之间发送消息。

但每次我更改服务器代码并保存文件时,都会收到一条错误消息,提示“已经有东西在监听端口 8080”,并且我的 Vite 开发服务器终止。如果我随后通过运行来启动备份我的 Vite 开发服务器npm run dev,那么一切都会再次正常工作,直到我对 WebSocket 服务器代码进行任何更改并保存文件,然后同样的事情将会重复。

我不想每次更改 WebSocket 服务器代码时都必须重新启动 Vite 开发服务器。如果可以的话,我宁愿 Vite 在每次启动之前自动关闭旧的 webSocket 服务器,为新的 webSocket 服务器腾出空间,这样它们就不会发生冲突。

我上面链接的教程显示了这个代码片段:

import adapter from '@sveltejs/adapter-node'
import preprocess from 'svelte-preprocess'

import { Server } from 'socket.io'

const webSocketServer = {
  name: 'webSocketServer',
  configureServer(server) {
    const io = new Server(server.httpServer)

    io.on('connection', (socket) => {
      socket.emit('eventFromServer', 'Hello, World ')
    })
  },
}

/** @type {import('@sveltejs/kit').Config} */
const config = {
  preprocess: preprocess(),
  kit: {
    adapter: adapter(),
    vite: {
      plugins: [webSocketServer],
    },
  },
}

export default config
Run Code Online (Sandbox Code Playgroud)

这段代码使用的是旧的 SvelteKit 版本,其中 Vite 配置是在文件内完成的svelte.config.js,因此布局有点不同,但看起来他们configureServer只是像我一样直接在方法内旋转他们的 Socket.io 服务器,但他们我正在利用现有的 Vite http 服务器,而不是像我一样创建一个新的服务器。我尝试这样做,但仍然遇到同样的问题。每次我尝试httpServer.listen(8080);使用 Vite 的 http 服务器时,我都会被告知服务器已经在侦听端口并且开发服务器终止。我还尝试使用require("http").createServer()它手动创建一个http服务器,但是(毫不奇怪)它也不起作用,并且其行为与我在这个问题开头所示的最初尝试相同。

本教程似乎以与我尝试启动我的服务器相同的方式启动 Socket.io 服务器,但它们似乎没有像我一样遇到任何冲突。我检查了 Socket.io 的文档,看看构造函数是否Server有内置的故障保护,以确保它不会在已经侦听该端口的情况下侦听该端口(并避免创建错误),但文档没有提供这方面的任何信息,所以我仍然不确定那里发生了什么。

有什么办法可以做我想做的事情,或者我是否完全以错误的方式来做这件事?我在互联网上几乎找不到任何关于此的信息。

另外,Socket.io 示例中发生了什么,使其能够在我的示例无法工作的情况下工作?Socket.io 正在做一些特别的事情吗?

这是我使用Vite内置http服务器的尝试。这与我的其他尝试的行为相同。 vite.config.ts

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;
        const webSocketServer = new WebSocketServer({
            noServer: true
        });
    
        webSocketServer.on("connection", (socket, request) => {
            socket.on("message", (data, isBinary) => {
                console.log(`Recieved ${data}`);
            });
        
            socket.send("hi c:");
        });

        httpServer.on("upgrade", (request: any, socket: any, head: any) => {
            webSocketServer.handleUpgrade(request, socket, head, socket => {
                webSocketServer.emit("connection", socket, request);
            });
        });

        httpServer.listen(8080);
    }
}

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

export default config;
Run Code Online (Sandbox Code Playgroud)

Mat*_*att 5

ws支持使用现有的server(如 socket.io)进行初始化

不要将应用程序逻辑存储在 vite/svelte 配置中,因为当 vite 不可用时,生产构建将需要它(虽然我不熟悉 sveltekit,所以也许它有一些魔力?)。为 ws 设置创建一个独立文件:

import { WebSocketServer } from "ws";

export const configureServer = (server) => {
  const webSocketServer = new WebSocketServer({
    server: server.httpServer,
  });
    
  webSocketServer.on("connection", (socket, request) => {
    socket.on("message", (data, isBinary) => {
      console.log(`Recieved ${data}`);
    });
        
    socket.send("test from server");
  });
}

export const webSocketServer = {
    name: "webSocketServer",
    configureServer,
}
Run Code Online (Sandbox Code Playgroud)

然后您应该能够使用您的版本,webSocketServer例如 socket.io 示例,因为它们都附加到“@sveltejs/adapter-node”服务器。

import adapter from '@sveltejs/adapter-node'
import { webSocketServer } from './sockets.js';

/** @type {import('@sveltejs/kit').Config} */
const config = {
  kit: {
    adapter: adapter(),
    vite: {
      plugins: [webSocketServer],
    },
  },
}

export default config
Run Code Online (Sandbox Code Playgroud)

configureServer现在可以在您为生产设置自定义服务器时重复使用。