You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决NuxtJS 3 Nitro服务器中Socket.io仅开发环境可用问题

Nuxt 3 Nitro + Socket.io 生产环境WebSocket无响应问题解决

问题背景

在NuxtJS 3的Nitro服务器中集成Socket.io时,开发模式下WebSocket功能正常,但部署到生产环境后无法接收响应,怀疑是端口未与HTTP服务器保持一致导致。

原module/socket.ts代码:

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

const clients: any = {};

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('new connection', socket.id)
         clients[socket.id] = socket.handshake.query.clientId;
       })


      io.on('connect', (socket) => {

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

          const customId = Object.keys(clients).find(key => clients[key] === data['id']);
          if (customId) {
            console.log('sending to', customId)
            socket.to(customId).emit('widget', data)
          }
        })

        socket.on('disconnecting', () => {
          console.log('disconnected', socket.id)
          delete clients[socket.id];
        })
      });
    })
  },
})

解决方案

1. 统一端口与生产环境地址绑定

  • Nitro在生产环境可能通过环境变量指定端口(如PORT),Socket.io直接绑定到Nitro传入的server实例即可确保共用同一端口,无需额外配置端口。
  • 客户端连接时不要硬编码localhost:3000,需根据环境动态生成地址:开发环境用window.location.origin,生产环境自动适配部署域名。

2. 添加生产环境必要的Socket.io配置

生产环境需配置CORS(避免跨域拦截),并明确Socket.io的路径(防止与Nitro路由冲突),修改Socket.io初始化代码:

const io = new Server(server, {
  cors: {
    origin: process.env.NODE_ENV === 'production' ? process.env.NUXT_PUBLIC_APP_URL : '*',
    methods: ['GET', 'POST']
  },
  path: '/socket.io/'
})

3. 合并重复的连接事件监听

原代码同时监听connection和connect(二者为同一事件),会导致逻辑重复执行,合并为单个监听:

io.on('connection', (socket) => {
  console.log('new connection', socket.id)
  clients[socket.id] = socket.handshake.query.clientId;

  // 处理message事件
  socket.on('message', function message(data: any) {
    console.log('message received: %s', data)
    const customId = Object.keys(clients).find(key => clients[key] === data['id']);
    if (customId) {
      console.log('sending to', customId)
      socket.to(customId).emit('widget', data)
    }
  })

  // 处理断开连接
  socket.on('disconnecting', () => {
    console.log('disconnected', socket.id)
    delete clients[socket.id];
  })
})

4. 确认生产环境反向代理配置(若使用)

如果生产环境用Nginx等反向代理,需配置WebSocket支持:

location /socket.io/ {
  proxy_pass http://localhost:3000;
  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";
  proxy_set_header Host $host;
}

修正后的完整module/socket.ts代码

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

const clients: Record<string, string> = {};

export default defineNuxtModule({
  setup(options, nuxt) {
    nuxt.hook('listen', (server) => {
      console.log('Socket listen', server.address(), server.eventNames())
      // 配置生产环境CORS和路径
      const io = new Server(server, {
        cors: {
          origin: process.env.NODE_ENV === 'production' ? process.env.NUXT_PUBLIC_APP_URL : '*',
          methods: ['GET', 'POST']
        },
        path: '/socket.io/'
      })

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

      io.on('connection', (socket) => {
        console.log('new connection', socket.id)
        const clientId = socket.handshake.query.clientId as string;
        if (clientId) {
          clients[socket.id] = clientId;
        }

        socket.on('message', (data: any) => {
          console.log('message received: %o', data)
          const customId = Object.keys(clients).find(key => clients[key] === data.id);
          if (customId) {
            console.log('sending to', customId)
            socket.to(customId).emit('widget', data)
          }
        })

        socket.on('disconnecting', () => {
          console.log('disconnected', socket.id)
          delete clients[socket.id];
        })
      })
    })
  },
})

内容的提问来源于stack exchange,提问作者Bruno Belloni

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 08:51:00