Next.js 13.2+路由处理器中如何构建WebSocket?
在Next.js 13.2+中构建WebSocket的解决方案
Next.js 13.2+的App Router路由处理器(app目录下的route.js)基于Fetch API规范,无法直接处理WebSocket所需的HTTP Upgrade请求,这就是你在GET处理器中尝试使用WebSocket失败的原因,且目前官方文档确实未提供App Router内直接支持WebSocket的方案。
以下是两种可行的实现方式:
方案一:使用Pages Router的API路由
Pages Router的API路由基于Node.js HTTP服务器,可以直接处理WebSocket连接升级:
- 首先安装WebSocket库(以
ws为例):
npm install ws
- 在
pages/api/ws.js中创建WebSocket处理逻辑:
import { WebSocketServer } from 'ws'; export default function handler(req, res) { // 检查是否为WebSocket升级请求 if (req.method === 'GET' && req.headers.upgrade === 'websocket') { const wss = new WebSocketServer({ noServer: true }); // 升级HTTP连接到WebSocket协议 wss.handleUpgrade(req, req.socket, Buffer.alloc(0), (ws) => { wss.emit('connection', ws, req); }); // 处理客户端连接 wss.on('connection', (ws) => { console.log('Client connected'); // 接收客户端消息并返回响应 ws.on('message', (data) => { const message = data.toString(); console.log(`Received: ${message}`); ws.send(`Server response: ${message}`); }); // 处理客户端断开连接 ws.on('close', () => { console.log('Client disconnected'); }); }); // 确保连接关闭时清理资源 res.socket.on('close', () => { wss.close(); }); } else { res.status(404).send('WebSocket endpoint only'); } } // 禁用Next.js默认的请求解析和处理 export const config = { api: { bodyParser: false, externalResolver: true, }, };
- 前端页面中连接WebSocket:
// 示例:在客户端组件中连接 'use client'; import { useEffect } from 'react'; export default function WebSocketClient() { useEffect(() => { const ws = new WebSocket(`ws://${window.location.host}/api/ws`); ws.onopen = () => { ws.send('Hello from client!'); }; ws.onmessage = (event) => { console.log('Server message:', event.data); }; ws.onclose = () => { console.log('Disconnected from server'); }; // 组件卸载时关闭连接 return () => { ws.close(); }; }, []); return <div>WebSocket client running</div>; }
方案二:使用自定义服务器(完全控制HTTP服务器)
如果你需要对服务器有完全控制权,可以搭建自定义Express/Node.js服务器并集成WebSocket:
- 安装依赖:
npm install express ws next
- 创建根目录下的
server.js:
const express = require('express'); const next = require('next'); const { createServer } = require('http'); const { WebSocketServer } = require('ws'); const dev = process.env.NODE_ENV !== 'production'; const app = next({ dev }); const handle = app.getRequestHandler(); app.prepare().then(() => { const expressApp = express(); const httpServer = createServer(expressApp); const wss = new WebSocketServer({ server: httpServer }); // 处理WebSocket连接 wss.on('connection', (ws) => { ws.on('message', (data) => { console.log(`Received message: ${data.toString()}`); ws.send(`Echo: ${data.toString()}`); }); }); // 让Next.js处理所有其他路由 expressApp.all('*', (req, res) => { return handle(req, res); }); httpServer.listen(3000, () => { console.log('Server running on http://localhost:3000'); }); });
- 修改
package.json的启动脚本:
{ "scripts": { "dev": "node server.js", "build": "next build", "start": "NODE_ENV=production node server.js" } }
注意事项
- App Router路由处理器目前不支持WebSocket,这是由其基于Fetch API的设计限制决定的,后续官方可能会推出相关支持,但当前阶段只能通过上述两种方案实现。
- 如果使用Vercel部署,Pages Router的WebSocket API路由需要使用Serverless Functions,而自定义服务器则需要部署到支持Node.js服务器的平台(如Vercel的Edge Functions不支持WebSocket,需用Serverless或自定义部署)。
内容的提问来源于stack exchange,提问作者Abdelmanan Abdelrahman
相关产品推荐
相关产品推荐

