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

NextJS13.4.19 App Router中Socket.io服务搭建失败求助

问题分析与解决方案

你的问题核心在于NextJS 13.4.19 App Router的API路由规则与Pages Router完全不同,同时Socket.io在App Router下的挂载方式需要调整,导致出现404错误和多渲染器警告。以下是分步修复方案:


1. 调整Socket.io服务器挂载方式(使用自定义服务器)

App Router的API路由基于Web标准Request/Response,无法直接获取res.socket.server,因此推荐使用自定义服务器挂载Socket.io,这是最稳定的方案。

步骤1:创建自定义服务器文件

在项目根目录新建server.ts,内容如下:

import { createServer } from "http";
import { parse } from "url";
import next from "next";
import { Server } from "socket.io";

const dev = process.env.NODE_ENV !== "production";
const hostname = "localhost";
const port = 3000;

// 初始化NextJS应用
const app = next({ dev, hostname, port });
const handle = app.getRequestHandler();

app.prepare().then(() => {
  const httpServer = createServer(async (req, res) => {
    try {
      const parsedUrl = parse(req.url!, true);
      await handle(req, res, parsedUrl);
    } catch (err) {
      console.error("请求处理失败", req.url, err);
      res.statusCode = 500;
      res.end("Internal Server Error");
    }
  });

  // 初始化Socket.io服务器
  const io = new Server(httpServer, {
    path: "/api/socket/io", // 指定Socket.io路径,避免与NextJS路由冲突
    cors: {
      origin: "http://localhost:3000", // 开发环境允许本地跨域
      methods: ["GET", "POST"],
    },
  });

  // 监听Socket连接事件
  io.on("connection", (socket) => {
    console.log(`客户端已连接: ${socket.id}`);

    // 监听客户端发送的input-change事件
    socket.on("input-change", (msg) => {
      socket.broadcast.emit("update-input", msg);
    });

    // 监听断开连接事件
    socket.on("disconnect", () => {
      console.log(`客户端已断开: ${socket.id}`);
    });
  });

  // 启动服务器
  httpServer.listen(port, () => {
    console.log(`> 服务已启动: http://${hostname}:${port}`);
  });
});

步骤2:修改package.json启动脚本

替换原有启动命令,使用自定义服务器启动项目:

{
  "scripts": {
    "dev": "node server.ts",
    "build": "next build",
    "start": "NODE_ENV=production node server.ts"
  }
}

2. 修复客户端组件代码

调整Socket.io初始化逻辑,匹配自定义服务器的配置:

'use client'
import { FC, useState, useEffect } from 'react'
import io from "socket.io-client";

import type { Socket } from 'socket.io-client'

let socket: undefined | Socket

export const DashboardMessagesPage: FC = () => {
  const [isContactInfoOpened, setIsContactInfoOpened] = useState(false);
  const [isRightSearchWidgetOpened, setIsRightSearchWidgetOpened] = useState(false);
  const [inputValue, setInputValue] = useState(''); // 用于接收同步的输入内容

  useEffect(() => {
    // 初始化Socket连接
    socket = io({
      path: "/api/socket/io", // 与服务器端配置的路径一致
      transports: ["websocket", "polling"], // 优先使用WebSocket传输
    })

    // 监听连接成功事件
    socket.on('connect', () => {
      console.log('Socket连接成功')
    })

    // 监听服务器推送的update-input事件
    socket.on('update-input', (msg) => {
      setInputValue(msg)
      console.log('收到输入更新:', msg)
    })

    // 组件卸载时断开Socket连接
    return () => {
      socket?.disconnect()
    }
  }, [])

  // 示例:发送输入变化到服务器
  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const value = e.target.value
    setInputValue(value)
    socket?.emit('input-change', value)
  }

  return (
    <>
      {/* 你的原有页面内容 */}
      <div>
        <input 
          type="text" 
          value={inputValue} 
          onChange={handleInputChange}
          placeholder="输入内容测试同步..."
        />
        <p>同步内容: {inputValue}</p>
      </div>
    </>
  )
}

3. 清理旧文件

删除原来的app/api/socket.ts文件,因为现在使用自定义服务器挂载Socket.io,不再需要该文件。


4. 测试运行

执行npm run dev启动项目,打开两个浏览器窗口访问仪表盘页面,在一个窗口输入内容,另一个窗口应该能同步收到更新,控制台也会显示连接日志。


关于"多渲染器"警告

该警告通常是服务器组件与客户端组件的上下文冲突导致,使用自定义服务器后会自动消失。如果仍存在,需确保:

  • 所有使用Socket.io的组件都添加了'use client'指令
  • 不在服务器组件中初始化Socket.io相关逻辑

内容的提问来源于stack exchange,提问作者Royal WebGuru

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 11:38:10