Nuxt 3生产环境中Socket.io WebSocket无法正常工作求助
Nuxt3生产环境Socket.io连接失败问题排查与解决
问题描述
在Nuxt3(v3.0.0-rc.8)应用中集成Socket.io,开发模式下WebSocket连接正常,但生产环境启动后客户端无法连接Socket服务,出现WebSocket握手失败、返回404的错误。
相关配置与代码文件
nuxt.config.ts
import { defineNuxtConfig } from 'nuxt'; // https://v3.nuxtjs.org/api/configuration/nuxt.config export default defineNuxtConfig({ css: [ 'primevue/resources/themes/saga-blue/theme.css', 'primevue/resources/primevue.css', 'primeicons/primeicons.css' ], build: { transpile: [ 'primevue' ], }, modules: [ './modules/socket' ] })
modules/sockets.ts
import { Server } from 'socket.io'; import { defineNuxtModule } from '@nuxt/kit'; export default defineNuxtModule({ setup(_, nuxt) { console.log('Socket Read'); 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`) }) }) }); }, });
plugins/socket.client.ts
import io from 'socket.io-client'; export default defineNuxtPlugin(() => { const socket = io('http://localhost:3000'); return { provide: { io: socket } } });
app.vue
<template> <button @click="sendMessage" class="btn btn-primary">Send Message</button> </template> <script setup lang="ts"> const { $io } = useNuxtApp(); const sendMessage = () => { console.log('Click'); $io.emit("message", "new message sent"); }; </script>
package.json
{ "private": true, "scripts": { "build": "nuxi build", "dev": "nuxi dev", "generate": "nuxi generate", "preview": "nuxi preview", "start": "node .output/server/index.mjs" }, "devDependencies": { "nuxt": "^3.0.0-rc.8" }, "dependencies": { "primeflex": "^3.2.1", "primeicons": "^5.0.0", "primevue": "^3.16.1", "socket.io": "^4.5.2", "socket.io-client": "^4.5.2" } }
问题解决步骤
1. 修正客户端连接地址硬编码
生产环境中客户端不能硬编码localhost:3000,需自动适配当前部署域名:
// plugins/socket.client.ts import io from 'socket.io-client'; export default defineNuxtPlugin(() => { // 自动使用当前页面的域名与端口,无需硬编码 const socket = io({ transports: ['websocket'], // 强制使用WebSocket传输,避免轮询触发的404 autoConnect: true }); return { provide: { io: socket } } });
2. 简化服务端监听逻辑
connection与connect为同一事件的不同别名,重复监听易引发逻辑冲突,保留一个即可:
// modules/sockets.ts import { Server } from 'socket.io'; import { defineNuxtModule } from '@nuxt/kit'; export default defineNuxtModule({ setup(_, nuxt) { console.log('Socket Read'); nuxt.hook('listen', (server) => { console.log('Socket listen', server.address(), server.eventNames()) const io = new Server(server, { cors: { origin: "*", // 生产环境建议替换为具体前端域名,如"https://your-domain.com" methods: ["GET", "POST"] } }) nuxt.hook('close', () => io.close()) io.on('connection', (socket) => { console.log('Connection', socket.id) 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`) }) }) }); }, });
3. 确保生产环境正确启动
生产环境需先构建再启动服务,使用以下命令:
npm run build npm run start
注意:不要使用npm run preview,该命令用于静态站点预览,不支持Node服务端的Socket.io逻辑。
4. 升级Nuxt版本到稳定版
当前使用的rc.8为早期测试版本,存在服务端钩子兼容性问题,升级到稳定版可避免潜在异常:
npm install nuxt@latest
内容的提问来源于stack exchange,提问作者Anthony Jekanyika
相关产品推荐
相关产品推荐

