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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 20:39:19