Next.js开发SSE本地正常,部署到Vercel后异常的问题求助
Next.js SSE部署到Vercel后异常问题
我用Next.js开发了Server-sent Events(SSE)功能,本地运行正常,但部署到Vercel后出现异常:仅当调用res.end()时,客户端的onmessage事件才会被触发。
服务端代码
export default (req, res) => { // 设置SSE相关响应头 res.setHeader('Content-Type', 'text/event-stream') res.setHeader('Cache-Control', 'no-cache') res.setHeader('Connection', 'keep-alive') res.setHeader("Content-Encoding", "none"); // 发送初始ping消息 res.write('data: ping\n\n') // 每5秒发送一次消息 const intervalId = setInterval(() => { res.write('data: message\n\n') }, 5000) // 客户端断开连接时清理资源 res.on('close', () => { clearInterval(intervalId) res.end() }) }
客户端代码
import React, { useState } from 'react' const IndexPage = () => { const [source, setSource] = useState(null) const handleStart = () => { const newSource = new EventSource('/api/sse') newSource.onmessage = (event) => { console.log('Received message:', event.data) } setSource(newSource) } const handleStop = () => { if (source) { source.close() setSource(null) } } return ( <div> <button onClick={handleStart}>Start</button> <button onClick={handleStop}>Stop</button> </div> ) } export default IndexPage
问题原因
Vercel的Serverless Functions默认启用响应缓冲机制,会将所有响应内容缓存直到调用res.end()才一次性返回给客户端。而SSE依赖分块传输(Chunked Transfer Encoding)实现实时消息推送,这种缓冲机制直接阻断了流式响应的能力,导致只有当响应结束时客户端才能收到所有消息。
解决方案
使用Vercel的Edge Functions替代Serverless Functions,Edge Runtime原生支持流式响应,不会缓冲内容,完美适配SSE场景。修改服务端代码如下:
export const config = { runtime: 'edge' }; export default async function handler(req) { const encoder = new TextEncoder(); const stream = new ReadableStream({ async start(controller) { // 发送初始ping消息 controller.enqueue(encoder.encode('data: ping\n\n')); // 每5秒推送一次消息 const intervalId = setInterval(() => { controller.enqueue(encoder.encode('data: message\n\n')); }, 5000); // 监听客户端断开连接事件,清理定时器并关闭流 req.signal.addEventListener('abort', () => { clearInterval(intervalId); controller.close(); }); }, }); return new Response(stream, { headers: { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', 'Content-Encoding': 'none', }, }); }
说明
- 通过
export const config = { runtime: 'edge' };指定使用Edge Runtime - 使用标准Web API的
ReadableStream实现流式响应,替代Node.js的res.write方法 - 利用
req.signal监听客户端断开连接事件,及时清理资源
内容的提问来源于stack exchange,提问作者CodeAlien
相关产品推荐
相关产品推荐

