Next.js App Router 里做 AI 流式输出

最近把一个 AI 对话页迁到 Next.js App Router。流式输出在 Pages Router 时代我闭着眼都能写,到了 App Router + RSC + server action 这套新范式,卡了我大半天。把过关的路记下来。

第一个纠结:用 Route Handler 还是 Server Action

App Router 下做流式有两条路。

Route Handler( app/api/chat/route.ts ) 是最稳的,本质还是返回一个标准的 Response,body 塞一个 ReadableStream:

javascript 复制代码
export async function POST(req: Request) {
  const stream = new ReadableStream({
    async start(controller) {
      const res = await callModel(/* ... */)
      for await (const chunk of res) {
        controller.enqueue(
          new TextEncoder().encode(chunk.delta)
        )
      }
      controller.close()
    },
  })
  return new Response(stream, {
    headers: { 'Content-Type': 'text/event-stream' },
  })
}

客户端老老实实 fetch + getReader() 读,跟以前没两样。

Server Action 看起来更"新潮",能直接在组件里 await 调用。但纯 server action 做逐字流式其实很别扭------它是为表单提交和数据变更设计的,不是天生为长连接流式准备的。要硬做得配合 useActionState 或返回一个可迭代的东西,绕。我试了一版,体感不如 Route Handler 直接。

我的选择

流式走 Route Handler,server action 只用来做非流式的副作用,比如把这轮对话存库、更新会话标题。各干各的,别让 server action 硬扛流式。

踩到的坑

坑一:动态渲染。 默认有缓存,对话接口必须显式 export const dynamic = 'force-dynamic',否则你会发现流式接口被缓存住,第二次问返回上次的内容,人都傻了。

坑二:客户端组件边界。 渲染对话气泡、维护输入状态的那部分必须 'use client'。我一开始忘加,useState 直接报错,App Router 默认是 server component 这点得时刻记着。

坑三:Edge runtime 的流式更顺,但部分 Node API 用不了,按需取舍。

没做完美的地方

server action 存库失败时的回滚我做得很糙,目前就打个日志,没做真正的补偿。先用着。

模型那一端我接的讯飞 MaaS,现成的推理服务直接调,不折腾自建。你们 App Router 下流式是走 Handler 还是 Action?评论区交个底。

相关推荐
回眸&啤酒鸭6 天前
【回眸】Minicart 电商购物车核心功能落地指南
人工智能
一隅论数智6 天前
给AI一张“业务概念地图“:本体如何从哲学走向企业智能
大数据·人工智能·经验分享·笔记·学习·学习方法·政务
AI的探索之旅6 天前
97 个 OpenCV 实例(三十):双目立体,从标定到点云
人工智能·opencv·计算机视觉
AlbertZein6 天前
Step-5-Preview 上手实测:3D 游戏、金融分析、网页设计一次跑完
人工智能·aigc
LaughingZhu6 天前
Product Hunt 每日热榜 | 2026-09-19
人工智能·深度学习·神经网络·搜索引擎·百度
美狐美颜SDK开放平台6 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
wukangjupingbb6 天前
智能网联汽车安全能力框架
人工智能
龙亘川6 天前
明月照湾区,智启新赛道:从顶流文旅IP盛会看智慧文旅升级路径
人工智能·智慧城市·开源软件·数据可视化
飞猫的边缘AI6 天前
边缘AI应用:家用AI摄像头怎么做数据训练?
人工智能·边缘计算·ai算法·边缘ai