首页
/ Nuxt 中集成 Socket.IO 全解:socket.io 官方示例的开发、构建与生产预览实战

Nuxt 中集成 Socket.IO 全解:socket.io 官方示例的开发、构建与生产预览实战

2026-09-04 13:39:23作者:龚格成

本篇基于 socket.io 仓库官方的 Nuxt 示例,完整讲解如何将 Socket.IO 的 WebSocket 双向通信能力嵌入 Nuxt 4 服务端(Nitro 引擎),并覆盖从依赖安装、开发服务器启动,到生产构建与本地预览的完整流程。读完后你将掌握:如何在 Nuxt 中通过 Nitro 插件挂载 socket.io 服务端、如何让 HTTP 轮询与 WebSocket 升级请求正确路由到 engine.io,以及客户端如何创建全局 socket 并展示连接状态。

示例定位与文件结构

该示例是 Nuxt Minimal Starter 的 socket.io 集成版本,用于演示在 Nuxt 全栈框架中运行 Socket.IO 服务端与客户端的最小可行方案。核心文件职责如下:

文件 职责
nuxt.config.ts Nuxt 配置,开启 Nitro 的 WebSocket 实验特性
server/plugins/socket.io.ts Nitro 插件:创建并挂载 socket.io 服务端
app/components/socket.ts 客户端:创建全局 socket 单例
app/components/Connection.client.vue 客户端组件:展示连接状态与当前传输层
app/app.vue 应用入口,渲染 <Connection /> 组件
package.json 依赖与 npm scripts 定义

一、环境准备:安装依赖

按照 README 的 Setup 章节,先安装依赖。官方支持 npm、pnpm、yarn、bun 四种包管理器,任选其一:

# npm
npm install

# pnpm
pnpm install

# yarn
yynarn install

# bun
bun install

注意:bunyarn 分支下应分别执行 bun installyarn install

package.json 可以看到示例锁定(范围声明)的核心依赖版本,可作为集成时选型参考:

依赖 版本范围 说明
nuxt ^4.4.6 Nuxt 4,内置 Nitro 服务端引擎
socket.io ^4.8.3 服务端库
socket.io-client ^4.8.3 客户端库(与同版本服务端配套)
vue ^3.5.34 Vue 3
vue-router ^5.0.7 路由

另外 "postinstall": "nuxt prepare" 会在每次安装后自动执行 nuxt prepare,生成 .nuxt 目录下的类型声明,使 server/tsconfig.jsonextends "../.nuxt/tsconfig.server.json" 能够正常解析,这是 Nitro 服务端代码获得类型提示的前提。

二、启动开发服务器

安装完成后启动开发服务器,默认监听 http://localhost:3000

# npm
npm run dev

# pnpm
pnpm dev

# yarn
yarn dev

# bun
bun run dev

这些脚本对应 package.json 中的 "dev": "nuxt dev"。启动后,Nuxt 会扫描 server/plugins/ 目录并执行其中的 Nitro 插件(即下一节详述的 socket.io 挂载逻辑),随后客户端即可通过浏览器访问首页看到连接状态面板。

三、关键配置:开启 Nitro 的 WebSocket 实验特性

整个示例能跑通 WebSocket 升级(从 polling 升级为 websocket 传输层)的关键,在 nuxt.config.ts 中:

export default defineNuxtConfig({
  compatibilityDate: '2025-07-15',
  devtools: {
    enabled: true
  },
  nitro: {
    experimental: {
      websocket: true
    },
  }
})

逐段说明:

  • compatibilityDate: '2025-07-15':Nuxt 4 的兼容性基线日期,用于锁定 Nitro/Vite 的行为版本;
  • devtools.enabled: true:开启 Nuxt DevTools 开发工具;
  • nitro.experimental.websocket: true这是示例的核心开关。Nitro 默认不处理 WebSocket 升级请求,开启该实验特性后,Nitro 内置的 HTTP 服务器才会支持将 Upgrade: websocket 请求交给插件声明的 websocket.open 回调处理——没有这一行,Socket.IO 只能停留在 HTTP 轮询,无法完成传输层升级。

四、服务端核心:用 Nitro 插件挂载 Socket.IO

server/plugins/socket.io.ts 是服务端全部逻辑所在,完整代码如下:

import type { NitroApp } from "nitropack";
import { Server as Engine } from "engine.io";
import { Server } from "socket.io";
import { defineEventHandler } from "h3";

export default defineNitroPlugin((nitroApp: NitroApp) => {
  const engine = new Engine();
  const io = new Server();

  io.bind(engine);

  io.on("connection", (socket) => {
    // ...
  });

  nitroApp.router.use("/socket.io/", defineEventHandler({
    handler(event) {
      engine.handleRequest(event.node.req, event.node.res);
      event._handled = true;
    },
    websocket: {
      open(peer) {
        // crossws >= 0.3.0
        // @ts-expect-error private method and property
        engine.prepare(peer._internal.nodeReq);
        // @ts-expect-error private method and property
        engine.onWebSocket(peer._internal.nodeReq, peer._internal.nodeReq.socket, peer.websocket);

        // crossws < 0.3.0
        // const context = peer.ctx.node;
        // // @ts-expect-error private method
        // engine.prepare(context.req);
        // // @ts-expect-error private method
        // engine.onWebSocket(context.req, context.req.socket, context.ws);
      }
    }
  }));
});

挂载思路拆解

Socket.IO 常规用法是 httpServer.listen(),由 node 的 http.Server 同时承担静态资源与升级事件的分发。但 Nuxt 中 HTTP 服务器归 Nitro 所有,无法直接把 socket.ioServer 绑到一个独立端口上再暴露 /socket.io/ 路径,因此示例采用了 “无 http 模式 + 手动路由” 的方案:

  1. new Engine() 独立创建 engine.io 实例。此时不传入 http.Server,engine.io 处于待挂载状态。
  2. new Server() + io.bind(engine):socket.io 的 Server 不直接绑定 http 服务器,而是 bind 到上一步的 engine 实例上,由 engine 负责底层传输层管理。
  3. nitroApp.router.use("/socket.io/", ...):把 Socket.IO 约定的协议路径 /socket.io/(含 polling 的 HTTP 请求)注册到 Nitro 的 h3 路由上,请求会被 h3 按前缀匹配并分发。
  4. handler(event) 处理 HTTP 轮询:将 event.node.req / event.node.res 交给 engine.handleRequest(req, res),对应 engine.io 源码中的 handleRequest 方法,它负责解析 ?EIO=4&transport=polling 之类的 Engine.IO 协议请求、维持轮询会话。随后 event._handled = true 告知 h3 该响应已由中间层处理完毕,h3 不再兜底。
  5. websocket.open(peer) 处理 WebSocket 升级:当 Nitro(开启 nitro.experimental.websocket 后)拦截到 /socket.io/?...&transport=websocket 的 Upgrade 请求时,调用此回调。回调里先调 engine.prepare(req)——对应 engine.io 源码 prepare 方法,负责从升级请求头中解析出会话(sid)并找到对应的 pending 握手;再调 engine.onWebSocket(req, socket, ws)——对应 onWebSocket 方法,把底层 WebSocket 对象接入传输层,完成从 polling 到 websocket 的切换。

关于 crossws 版本兼容

peer 对象由 Nitro 依赖的 crossws 库提供。代码中 peer._internal.nodeReq 的取法要求 crossws >= 0.3.0,因此加了 // @ts-expect-error private method and property 注释(访问的是库内部私有成员,源码上并没有类型声明);同时保留了 crossws < 0.3.0 时代的 peer.ctx.node 写法作为注释,供低版本环境参考。这是一个典型的“适配上游库内部 API”的补丁式代码,若未来 Nitro 升级 crossws 大版本,此处是需要重点回归的兼容点。

业务逻辑挂载点

io.on("connection", (socket) => { ... }) 是业务事件的入口,示例中留空(// ...)以突出挂载流程本身。实际项目可在此发送欢迎消息、绑定频道,或结合 socket.io-adapter 实现跨节点广播。

五、客户端:全局 socket 单例与连接状态展示

socket 单例

app/components/socket.ts 只有两行:

import { io } from "socket.io-client";

export const socket = io();

io() 不传任何参数时,socket.io-client 会自动以当前页面同源、同端口为目标建立连接,即直连 Nuxt 开发服务器本身,天然适合全栈示例。模块级导出使整个前端共享同一个 Manager 与 socket 实例,避免每个组件各自握手。

连接状态组件

app/components/Connection.client.vue 展示了连接状态与当前传输层:

<script setup>
import { socket } from "./socket";

const isConnected = ref(false);
const transport = ref("N/A");

if (socket.connected) {
  onConnect();
}

function onConnect() {
  isConnected.value = true;
  transport.value = socket.io.engine.transport.name;

  socket.io.engine.on("upgrade", (rawTransport) => {
    transport.value = rawTransport.name;
  });
}

function onDisconnect() {
  isConnected.value = false;
  transport.value = "N/A";
}

socket.on("connect", onConnect);
socket.on("disconnect", onDisconnect);

onBeforeUnmount(() => {
  socket.off("connect", onConnect);
  socket.off("disconnect", onDisconnect);
});
</script>

<template>
<div>
  <p>Status: {{ isConnected ? "connected" : "disconnected" }}</p>
  <p>Transport: {{ transport }}</p>
</div>
</template>

几个值得注意的实现细节:

  • .client.vue 后缀:Nuxt 约定,以 .client 结尾的组件只在客户端水合后渲染、不参与 SSR。由于 socket 连接依赖浏览器环境中的 WebSocket,放在纯客户端组件里可以规避 SSR 阶段创建连接的问题;
  • socket.io.engine.transport.name:通过 socket.io.engine 拿到 engine.io-client 实例,再读取当前传输层名称(pollingwebsocket),直观呈现 Socket.IO 自动升级的行为;
  • engine.on("upgrade", ...):监听 engine 层的升级事件,在从长轮询切换到 WebSocket 的瞬间刷新 Transport 显示——这正是第四节 Nitro 侧 websocket.open 回调生效后的可见结果;
  • onBeforeUnmountsocket.off:组件卸载时解绑 connect/disconnect 监听,防止组件销毁后回调仍在执行。注意这里只移除监听而不 socket.close(),符合“单例 socket、多处消费”的共享模式。

app/app.vue 则在模板中渲染 <Connection />,完成从服务端到页面的闭环。

六、生产构建与本地预览

构建生产产物:

# npm
npm run build

# pnpm
pnpm build

# yarn
yarn build

# bun
bun run build

对应 package.json 中的 "build": "nuxt build",由 Nitro 输出服务端 bundle 与静态资源。

本地预览生产构建:

# npm
npm run preview

# pnpm
pnpm preview

# yarn
yarn preview

# bun
bun run preview

对应 "preview": "nuxt preview",用于在本地以接近部署形态的方式验证构建产物,包括 /socket.io/ 路径在 Nitro 生产模式下是否仍正确路由。package.json 中另有 "generate": "nuxt generate" 脚本用于静态站点生成,但对本例这类依赖持久 WebSocket 连接的服务端应用,部署时应以 build + 常驻进程的方式运行 Nitro 产物,具体部署形态建议参考 Nuxt 官方的部署文档(README 中给出的指引)。

七、小结与延伸阅读

本示例的最小集成路径可以概括为三步:

  1. 配置nuxt.config.ts 中打开 nitro.experimental.websocket
  2. 服务端:Nitro 插件中创建独立 EngineServerio.bind(engine) 后经 nitroApp.router.use("/socket.io/", ...) 把 HTTP 轮询与 WebSocket 升级分别交给 engine.handleRequestengine.prepare + engine.onWebSocket
  3. 客户端io() 同源单例 + 客户端专属组件展示连接与传输层状态。

若想继续深入,可以阅读仓库中 engine.io 服务端的 完整实现,理解握手、会话管理与传输层升级的协议细节;也可以对照 chat 示例connection-state-recovery 示例,了解事件广播、断线重连等更进一步的应用模式。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.79 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
988
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384