无法连接本地WebSocket服务器(Next、Prisma、TRPC订阅问题)
解决TRPC WebSocket订阅连接被拒绝(ERR_CONNECTION_REFUSED)的问题
核心原因
你只启动了Next.js应用(3000端口),但WebSocket服务器(ws.ts)并未运行,前端尝试连接3001端口时自然会被拒绝。
分步解决方案
1. 确认依赖安装
确保已安装ws模块(WebSocket服务器依赖):
npm install ws # 或用pnpm pnpm add ws
如果项目使用TypeScript,还需安装类型声明:
npm install -D @types/ws
2. 启动WebSocket服务器
你需要单独启动ws.ts,或者和Next.js同时启动:
方法一:单独启动(适合调试)
- 先安装
tsx(用于直接运行TypeScript文件,无需预编译):npm install -D tsx - 在
package.json的scripts中添加启动脚本:"scripts": { "dev": "next dev", "ws:dev": "tsx watch src/server/ws.ts" // 路径根据你的ws.ts实际位置调整 } - 新开一个终端,运行:
看到终端输出npm run ws:dev✅ WebSocket Server listening on ws://localhost:3001,说明WS服务器启动成功。
方法二:同时启动Next.js和WS服务器
- 安装
concurrently(用于同时运行多个命令):npm install -D concurrently - 修改
package.json的dev脚本:"scripts": { "dev": "concurrently \"next dev\" \"tsx watch src/server/ws.ts\"" } - 运行
npm run dev,两个服务会同时启动。
3. 修复api.ts中的链接配置错误
你的links数组重复添加了httpBatchLink,会导致非订阅请求被发送两次,修改为:
export const api = createTRPCNext<AppRouter>({ config({ ctx }) { return { transformer: superjson, links: [ // 日志链接放最前面,记录所有请求 loggerLink({ enabled: (opts) => process.env.NODE_ENV === "development" || (opts.direction === "down" && opts.result instanceof Error), }), // 拆分链接:订阅用WS,其他请求用HTTP splitLink({ condition: (op) => op.type === "subscription", true: wsLink({ client: wsClient }), false: httpBatchLink({ url }), }), ], headers() { if (ctx?.req) { return { ...ctx.req.headers } } return {} } }; }, ssr: false, });
4. 测试验证
- 确保Next.js(3000端口)和WS服务器(3001端口)都正常运行
- 打开前端页面,WS服务器终端会打印
➕➕ Connection (1),说明连接成功 - 在后端触发事件(比如
ee.emit('add', { id: 1, content: '测试通知' })),前端应该能收到数据并执行onData回调
额外注意事项
- 端口冲突:如果3001端口被占用,修改ws.ts中的
port值(比如3002),同时前端wsClient的url也要对应更新 - 上下文认证:因为你用了
protectedProcedure,要确保WS连接时能正确传递用户认证信息(比如从cookie或请求头中获取token,在createContext中处理)
内容的提问来源于stack exchange,提问作者Mark Anthony Cabilo
相关产品推荐
相关产品推荐

