如何在Nuxt 3中启动WebSocket服务器(socketIO或其他)?与Nuxt 2中的工作方式不同

ercv8c1e  于 2023-05-29  发布在  其他
关注(0)|答案(3)|浏览(706)

我试图将我的代码从Nuxt 2转换到Nuxt 3,我遇到了在Nuxt 3中创建WebSocket服务器的问题。
它在Nuxt 2中使用以下代码运行得非常好:

// Nuxt 2: modules/socket.js
import http from 'http'
import socketIO from 'socket.io'

export default function () {
    this.nuxt.hook('render:before', () => {
        const server = http.createServer(this.nuxt.renderer.app)
        const io = socketIO(server)

        this.nuxt.server.listen = (port, host) => new Promise(resolve => server.listen(port || 3000, host || 'localhost', resolve))
        this.nuxt.hook('close', () => new Promise(server.close))

        io.on('connection', (socket) => {
            console.log("CONNECTED")
        })
    })
}
// Nuxt 2: plugins/socket.client.js
import io from 'socket.io-client'
const socket = io('http://localhost:3000')

export default ({}, inject) => {
    inject('socket', socket)
}
<!-- Nuxt 2: pages/index.vue -->
<template>
<div>
    <p>Check socket status in Vue devtools...</p>
</div>
</template>

<script>
export default {
    computed: {
        socket() {
            return this.$socket ? this.$socket : {};
        }
    }
}
</script>

然而,在Nuxt 3中,我无法访问modules/socket.js文件中的this.nuxt.renderer.app(对于http.createServer(...)),并且我无法弄清楚如何在Nuxt3模块中的其他地方访问正确的renderer.app。我的Nuxt 3代码看起来像这样:

// Nuxt 3: modules/socket.js
import http from 'http'
import socketIO from 'socket.io'

export default (_, nuxt) => {
    // Note that I use the 'ready' hook here - render:before is apparently not included in Nuxt3.
    nuxt.hook('ready', renderer => {
        // nuxt.renderer is undefined, so I've tried with renderer.app instead, with no luck.
        const server = http.createServer(renderer.app)
        const io = socketIO(server)

        nuxt.server.listen = (port, host) => new Promise(resolve => server.listen(port || 3000, host || 'localhost', resolve))
        nuxt.hook('close', () => new Promise(server.close))
            
        io.on('connection', () => {
            console.log("CONNECTION")
        })
    })
}
// Nuxt 3: plugins/socket.client.js
import io from 'socket.io-client'

export default defineNuxtPlugin(() => {
    const socket = io('http://localhost:3000')

    return {
        provide: {
            socket: socket
        }
    }
})
<!-- Nuxt 3: app.vue -->
<template>
  <div>
      <p>Check socket status in Vue devtools...</p>
  </div>
</template>

<script setup>
    const { $socket } = useNuxtApp()    
</script>

我会为你做一个codesandbox链接,但每次我尝试,它打破之前,我甚至添加任何代码。我认为它还不能正确地与Nuxt3一起工作。有人在Nuxt 3模块中成功建立了WebSocket服务器吗?有人能看出我错过了什么吗?
我对任何工作解决方案都感兴趣,它不一定是socket.io

evrscar2

evrscar21#

我想出来了!
深入研究Nuxt 3代码,发现它们有一个listen钩子,它提供了我设置服务器所需的server参数。不过,这些信息真的很难找到。
我还设法简化了一点脚本。
以下是更新后的modules/socket.js

import { Server } from 'socket.io'

export default (_, nuxt) => {
    nuxt.hook('listen', server => {
        const io = new Server(server)

        nuxt.hook('close', () => io.close())
        
        io.on('connection', () => {
            console.log("CONNECTION")
        })
    })
}

其他一切都可以保持不变

gzjq41n4

gzjq41n42#

基于@ahbork的回复和Nuxt 3文档的补充,我在Vue 3 + Nuxt 3 + Typescript上得到了这个:

import { Server } from 'socket.io'
import { defineNuxtModule } from '@nuxt/kit'

export default defineNuxtModule({
  setup(options, nuxt) {
    nuxt.hook('listen', (server) => {
      console.log('Socket listen', server.address(), server.eventNames())
      const io = new Server(server)

      nuxt.hook('close', () => io.close())

      io.on('connection', (socket) => {
        console.log('Connection', socket.id)
      })

      io.on('connect', (socket) => {
        socket.emit('message', `welcome ${socket.id}`)
        socket.broadcast.emit('message', `${socket.id} joined`)

        socket.on('message', function message(data: any) {
          console.log('message received: %s', data)
          socket.emit('message', { data })
        })

        socket.on('disconnecting', () => {
          console.log('disconnected', socket.id)
          socket.broadcast.emit('message', `${socket.id} left`)
        })
      })
    })
  },
})
w8biq8rn

w8biq8rn3#

thx anbork我用同样的方法在/modules/wsServer.ts中创建文件

import { WebSocketServer } from "ws";
import { defineNuxtModule } from "@nuxt/kit";

export default defineNuxtModule({
  setup(options, nuxt) {
    nuxt.hook("listen", (server) => {
      const wss = new WebSocketServer({ server });
      nuxt.hook("close", () => wss.close());
      wss.on("connection", (ws) => {
        console.log("connection");
        ws.on("message", (data) => console.log("received: %s", data));
        ws.send("someting");
      });
    });
  },
});

在页面文件中

let ws;
onMounted(() => {
  const wsProtocol = window.location.protocol === "https:" ? "wss:" : "ws:";
  ws = new WebSocket(`${wsProtocol}//${window.location.host}`);
  ws.onopen = () => console.log("connected");
  ws.onmessage = ({ data }: any) => {
    console.log("data", data);
  };
});
const sendMessage = () => {
  ws.send("hello");
};

相关问题