如何避免Next.js中Socket.io在服务端和客户端重复实例化
Next.js 14 + Socket.IO 双连接问题解决指南
环境配置
- 客户端:Next.js 14
- 服务端:Express
- WebSocket框架:socket.io
核心代码
服务端(index.ts)
import * as socket from "socket.io"; import express from "express"; import http from "http"; import cors from "cors"; const app = express(); app.use(cors()); const server = http.createServer(app); const io = new socket.Server(server, { cors: { origin: true, }, }); io.on("connection", async (socket) => { console.log(`Connection established`, socket.id); socket.on("disconnect", () => { console.log("user disconnected", socket.id); }); socket.on("chat-message", (text) => { console.log(text); socket.broadcast.emit("chat-message", text); }); }); server.listen(4000, () => { console.log("Server running on http://localhost:4000"); });
客户端相关文件
1. app/lib/socket.ts
import { io } from 'socket.io-client'; const url = 'http://localhost:4000'; console.log(`initialize socket`); export const socket = io(url);
2. app/page.tsx(已添加"use client"指令)
问题现象
首次访问localhost:3000时,Socket会在服务端和客户端各初始化一次,服务端收到两次连接请求;后续新浏览器窗口访问时仅客户端初始化一次Socket,符合预期。
疑问解答
1. 为什么代码会在服务端和客户端各执行一次?
Next.js 14的App Router默认以**服务端组件(Server Components)**为核心渲染模式,服务端组件会在服务器上执行并生成HTML返回给客户端。即便你在page.tsx中添加了"use client",如果socket.ts没有被限制为仅客户端执行,服务端渲染page.tsx时会同步加载并执行socket.ts里的代码(包括创建Socket连接);当客户端拿到HTML后,又会执行客户端组件内的代码,再次创建Socket连接,最终导致双连接。
2. 如何阻止服务端执行该代码,仅在客户端初始化Socket?
有两种实用方案:
方案一:用环境判断包裹Socket创建逻辑
修改socket.ts,仅在浏览器环境(存在window对象)时初始化Socket:
import { io } from 'socket.io-client'; let socket: ReturnType<typeof io> | null = null; export const getSocket = () => { // 仅在客户端环境初始化Socket if (typeof window !== 'undefined' && !socket) { console.log(`initialize socket`); socket = io('http://localhost:4000'); } return socket; };
后续在客户端组件中调用getSocket()获取实例即可,服务端渲染时不会执行初始化逻辑。
方案二:将socket.ts标记为客户端组件
在socket.ts顶部添加"use client"指令,强制Next.js将其视为客户端组件,服务端渲染时不会执行其中代码:
"use client"; import { io } from 'socket.io-client'; const url = 'http://localhost:4000'; console.log(`initialize socket`); export const socket = io(url);
内容的提问来源于stack exchange,提问作者nburk
相关产品推荐
相关产品推荐

