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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 09:57:38