ByteNoteByteNote
Next.js Route Handlers 入门与实战
字

字节笔记本

2026年10月6日 · 约 9 分钟读完

Next.js Route Handlers 入门与实战

API中转
¥120

Next.js 的 App Router 提供了一套新的服务端接口方案:Route Handlers(路由处理程序)。它允许开发者使用 Web 标准的 Request 与 Response API,为特定路由编写自定义请求处理器,角色上等同于 Pages Router 时代的 API Routes。本文整理它的文件约定、缓存行为、常用 API,以及从旧版 API Routes 迁移时最常见的报错。

文件约定与方法支持

Route Handlers 定义在 app 目录下的 route.js 或 route.ts 文件中,支持 GET、POST、PUT、PATCH、DELETE、HEAD、OPTIONS 七种 HTTP 方法。当请求命中了未导出的方法时,Next.js 会返回 405 Method Not Allowed 响应。

typescript
export async function GET(request: Request) {
  // 处理 GET 请求
}

与 page.js、layout.js 类似,route 文件可以嵌套在 app 目录的任意层级,例如 app/api/posts/route.ts 对应路径 /api/posts。注意一条硬约束:同一个路由段层级下,route.js 与 page.js 不能共存。

Route Handlers 文件约定与请求处理流程

默认不缓存,GET 可开启

Route Handlers 默认不做缓存。若希望 GET 请求走静态缓存,可在文件中导出路由段配置,例如 export const dynamic = 'force-static'。同一个文件里即使 GET 被缓存,其他 HTTP 方法依然不会被缓存,这一点在调试时容易踩坑。

Cookies 与 Headers 的读写

Route Handlers 与 next/headers 提供的动态函数无缝集成。读取 Cookie 使用 cookies 函数,设置 Cookie 则可以在返回的 Response 上携带 Set-Cookie 响应头:

typescript
import { cookies } from 'next/headers';

export async function GET(request: Request) {
  const cookieStore = cookies();
  const token = cookieStore.get('token');

  return new Response('Hello, Next.js!', {
    status: 200,
    headers: { 'Set-Cookie': `token=${token.value}` },
  });
}

headers 函数返回的实例是只读的,读取 referer 之类的请求头很直接;需要设置响应头时,标准做法是构造新的 Response 并在其 headers 中带上相应字段。

一个值得留意的版本差异:在 Next.js 15 及之后的版本中,cookies()、headers() 与动态参数 params 都改成了异步,读取时需要加 await,例如 const cookieStore = await cookies()。老项目升级时要对照官方迁移指南逐项调整。

动态路由段

Route Handlers 支持动态路由段,便于基于动态数据创建请求处理器。params 对象会作为第二个参数传入处理函数:

typescript
export async function GET(
  request: Request,
  { params }: { params: { slug: string } }
) {
  const slug = params.slug;
}

从 API Routes 迁移:res.status is not a function

社区里反复出现的一个高频问题是:把 Pages Router 的写法原样搬进 App Router,用 NextApiRequest 与 NextApiResponse 声明参数,再在函数体里调用 res.status(),运行时直接抛出 TypeError: res.status is not a function。

根源在于两套模型的函数签名完全不同。Pages Router 的 API Routes 接收 req、res 两个参数,通过 res.status()、res.json() 操作响应对象;App Router 的 Route Handlers 第一个参数是标准 Request,处理结果通过返回 Response 给出:

typescript
export async function GET(request: Request) {
  return new Response('Hello world!', {
    status: 202,
    headers: { 'Content-Type': 'text/plain' },
  });
}

读取请求体的方式也随之变化:不再是 req.body,而是调用 await request.json() 或 request.text()。NextApiRequest 与 NextApiResponse 这两个类型只属于 Pages Router,理解这一点后,绝大多数迁移报错都能自行定位。

从 API Routes 到 Route Handlers 的迁移对照

流式响应:AI 应用的基础模式

流式传输常与大语言模型(LLM)配合,用于逐段生成 AI 内容。借助 Vercel AI SDK 提供的 streamText 与 StreamingTextResponse,可以在 POST 处理器中把模型输出以流的形式返回:

typescript
import { openai } from '@ai-sdk/openai';
import { StreamingTextResponse, streamText } from 'ai';

export async function POST(req: Request) {
  const { messages } = await req.json();
  const result = await streamText({
    model: openai('gpt-4-turbo'),
    messages,
  });

  return new StreamingTextResponse(result.toAIStream());
}

这是 AI 对话类应用服务端的基础模式。AI SDK 各大版本的流式 API 有差异,落地时请以所用版本文档为准。

FormData 与 CORS

处理表单数据使用标准的 request.formData():

typescript
export async function POST(request: Request) {
  const formData = await request.formData();
  const name = formData.get('name');
  const email = formData.get('email');
  return Response.json({ name, email });
}

CORS 方面,单个处理器可以直接在返回的 Response 上设置 Access-Control-Allow-Origin 等响应头;若要为多个 Route Handlers 统一添加,则建议使用 Middleware 或在 next.config.js 中集中配置。

结语

Route Handlers 用 Web 标准的 Request 与 Response 取代了旧版 API Routes 的自定义参数模型,配合文件约定、缓存开关、动态路由段与流式响应,足以承担 Next.js 应用中从简单接口到 AI 流式输出的各类服务端职责。从 Pages Router 迁移时,记住参数是 Request、返回是 Response 这一原则,就能避开大部分报错。

相关文章

分享: