Next.js 14 App Router集成TRPC WebSocket订阅配置问题咨询
TRPC WebSocket 订阅在 Next.js 14 App Router 中的实现指南
一、官方示例分开 prod/dev WS 配置的原因
官方将生产和开发环境的 WS 服务器分开配置,核心是两种环境的服务器运行机制、依赖宿主服务完全不同:
- 开发环境:Next.js 自带的 dev server 基于 webpack 热重载,无法直接集成 WebSocket 服务,因此需要单独启动一个独立的 WSS 服务器监听额外端口,和 dev server 并行运行。
- 生产环境:Next.js 生产服务器是标准 Node.js HTTP 服务器(或部署在托管平台时使用其服务),可以将 WS 服务直接挂载到现有 HTTP 服务器上,无需单独起端口,更符合生产部署规范。
- 额外差异:开发环境会开启调试日志、宽松的 CORS 配置(允许本地跨域),生产环境则关闭调试输出、严格配置跨域规则,分开配置能避免环境间的配置污染。
二、解决 createContext 中调用 cookies()/headers() 报错的问题
你遇到的 500 错误,本质是 WebSocket 握手请求的上下文和 Next.js HTTP 请求上下文不兼容:Next.js 的 cookies()、headers() 是专为 HTTP 请求设计的,依赖内部请求上下文对象,但 WebSocket 连接基于初始握手 HTTP 请求,无法直接调用这些内置函数。
解决方法是直接从 WebSocket 的握手请求中提取所需信息:
- 在
applyWSSHandler的createContext中,通过req参数(握手阶段的 HTTP 请求对象)获取 headers 和 cookies。 - 手动解析 cookie(需先安装
cookie包:npm install cookie)。
示例代码:
// src/server/trpc/wss.ts import { applyWSSHandler } from '@trpc/server/adapters/ws'; import { parse } from 'cookie'; import { appRouter } from './router'; import { createContext } from './context'; // 整合 dev/prod 配置的统一函数 export function setupWSS(server?: any) { const isProduction = process.env.NODE_ENV === 'production'; let wssHandler; if (isProduction) { // 生产环境:挂载到现有 HTTP 服务器 wssHandler = applyWSSHandler({ server, router: appRouter, createContext: async ({ req }) => { // 从握手请求中提取 headers 和 cookies const cookies = parse(req.headers.cookie || ''); const headers = req.headers; return createContext({ cookies, headers, // 其他上下文参数 }); }, }); } else { // 开发环境:启动独立 WSS 服务器 const WebSocket = require('ws'); const wss = new WebSocket.Server({ port: 3001 }); wssHandler = applyWSSHandler({ wss, router: appRouter, createContext: async ({ req }) => { const cookies = parse(req.headers.cookie || ''); const headers = req.headers; return createContext({ cookies, headers, }); }, }); console.log('WSS server running on ws://localhost:3001'); } return wssHandler; }
同时,调整 createContext 函数为接收手动传入的参数:
// src/server/trpc/context.ts export async function createContext(opts: { cookies: Record<string, string>; headers: Record<string, string | string[] | undefined>; }) { // 直接使用传入的 cookies 和 headers return { cookies: opts.cookies, headers: opts.headers, // 其他上下文逻辑,比如用户验证 }; }
三、高效实现 TRPC 订阅的额外建议
- 统一配置文件:用
NODE_ENV区分环境,把 dev/prod 的 WS 逻辑整合到单个文件中,避免代码冗余。 - 客户端连接适配:开发环境下客户端连接独立 WS 端口(如
ws://localhost:3001),生产环境下连接同域名的 WS 路径(如wss://your-domain.com/trpc),通过环境变量自动切换:// src/utils/trpc.ts const wsUrl = process.env.NODE_ENV === 'production' ? `wss://${window.location.host}/trpc` : 'ws://localhost:3001'; - 错误处理:添加 WS 连接失败的重连逻辑,提升用户体验。
- 部署注意事项:若部署到 Vercel 等 Serverless 平台,需注意部分平台仅支持 Edge Runtime 下的 WebSocket,需调整为 Edge 函数;若使用传统 Node.js 服务器(如 Express),直接挂载即可。
内容的提问来源于stack exchange,提问作者Flynn Hillier
相关产品推荐
相关产品推荐

