如何在开发模式下的下一个 js 自定义服务器中运行 websocket 服务器

Bil*_*oon 5 websocket node.js next.js

假设我想运行自定义的下一个 js 服务器,并接受同一服务器上的 websocket 连接,如何避免破坏下一个 js 开发服务器热重载,该服务器也在同一服务器上使用 websocket...

const { createServer } = require('http')
const WebSocket = require("ws")
const { parse } = require('url')
const next = require('next')

const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()

app.prepare().then(() => {
    const server = createServer((req, res) => handle(req, res, parse(req.url, true)))
    // pass the same server instance that is used by next js to the websocket server
    const wss = new WebSocket.Server({ server })

    wss.on("connection", async function connection(ws) {
      console.log('incoming connection', ws);    
      ws.onclose = () => {
        console.log('connection closed', wss.clients.size);
      };
    });

    server.listen(port, (err) => {
        if (err) throw err
        console.log(`> Ready on http://localhost:${port} and ws://localhost:${port}`)
    })
})
Run Code Online (Sandbox Code Playgroud)

我相信该服务器应该在生产构建版本中工作,以便在用于处理下一个 js 请求的同一服务器实例上创建 websocket 服务器,但是当我尝试这样做时,热模块重新加载停止工作,并且错误出现在chrome 开发工具控制台,因为它希望由 webpack 处理的 websocket 连接现在由我的自定义 websocket 服务器处理。

我怎样才能以某种方式将开发服务器的 websocket 连接路由到下一个,并将 webpack 和其他连接路由到我自己的处理程序?

我知道我可以在另一个端口上运行我的 websocket 服务器,但我想在与下一个 js 相同的服务器实例和相同端口上运行它。

Bil*_*oon 12

所以技巧是创建一个 websocket 服务器,并将 noServer 属性设置为 true,然后监听服务器升级事件,并根据路径名,不执行任何操作以允许下一个 js 执行该操作,或者将请求传递给 websocket我们创建的服务器...

const wss = new WebSocket.Server({ noServer: true })

server.on('upgrade', function (req, socket, head) {
    const { pathname } = parse(req.url, true);
    if (pathname !== '/_next/webpack-hmr') {
        wss.handleUpgrade(req, socket, head, function done(ws) {
            wss.emit('connection', ws, req);
        });
    }
});

Run Code Online (Sandbox Code Playgroud)

……所有的事情都是这样的……

const { createServer } = require('http')
const WebSocket = require("ws")
const { parse } = require('url')
const next = require('next')

const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()

app.prepare().then(() => {
    const server = createServer((req, res) => handle(req, res, parse(req.url, true)))
    const wss = new WebSocket.Server({ noServer: true })

    wss.on("connection", async function connection(ws) {
      console.log('incoming connection', ws);
      ws.onclose = () => {
        console.log('connection closed', wss.clients.size);
      };
    });

    server.on('upgrade', function (req, socket, head) {
        const { pathname } = parse(req.url, true);
        if (pathname !== '/_next/webpack-hmr') {
            wss.handleUpgrade(req, socket, head, function done(ws) {
                wss.emit('connection', ws, req);
            });
        }
    });

    server.listen(port, (err) => {
        if (err) throw err
        console.log(`> Ready on http://localhost:${port} and ws://localhost:${port}`)
    })
})
Run Code Online (Sandbox Code Playgroud)