跳转至

路由处理

原文地址:https://nextjs.org/docs/app/getting-started/route-handlers

路由处理程序允许您使用 Web 请求和响应 API 为给定路由创建自定义请求处理程序。

扩展

路由处理程序仅在 app 目录中可用。它们相当于pages目录中的 API 路由,这意味着您不需要同时使用 API 路由和路由处理程序。

1. 约定

路由处理程序在 app 目录内的 route.js|ts 文件中定义:

app/api/route.ts
export async function GET(request: Request) {}

路由处理程序可以嵌套在 app 目录内的任何位置,类似于 page.jslayout.js。但不能有与 page.js 处于同一路由段级别的 route.js 文件。

2. 支持的 HTTP 方法

支持以下 HTTP 方法:GETPOSTPUTPATCHDELETEHEADOPTIONS。如果调用不受支持的方法,Next.js 将返回 405 Method Not Allowed 响应。

3. 扩展的 NextRequestNextResponse API

除了支持本机请求和响应 API 之外,Next.js 还使用 NextRequestNextResponse 扩展它们,为高级用例提供方便的帮手。

4. 缓存

默认情况下不缓存路由处理程序。但是,您可以选择对 GET 方法进行缓存。其他支持的 HTTP 方法不会被缓存。要缓存 GET 方法,请在路由处理程序文件中使用路由配置选项,例如 export const dynamic = 'force-static'

app/item/route.ts
export const dynamic = 'force-static'

export async function GET() {
  const res = await fetch('https://data.mongodb-api.com/...', {
    headers: {
      'Content-Type': 'application/json',
      'API-Key': process.env.DATA_API_KEY,
    },
  })
  const data = await res.json()

  return Response.json({ data })
}

扩展

其他受支持的 HTTP 方法不会被缓存,即使它们与缓存的 GET 方法放在同一文件中也是如此。

4.1 使用缓存组件

启用缓存组件后,GET 路由处理程序将遵循与应用程序中的普通 UI 路由相同的模型。它们默认在请求时运行,当它们不访问动态或运行时数据时可以预渲染,并且您可以使用 use cache 在静态响应中包含动态数据。

静态示例:不访问动态或运行时数据,因此它将在构建时预渲染。

app/api/route.ts
1
2
3
4
5
export async function GET() {
  return Response.json({
    projectName: 'Next.js',
  })
}

动态示例: 访问非确定性操作。在构建期间,当调用 Math.random() 时,预渲染会停止,从而推迟到请求时渲染。

app/api/random-number/route.ts
1
2
3
4
5
export async function GET() {
  return Response.json({
    randomNumber: Math.random(),
  })
}

运行时数据示例:访问特定于请求的数据。当调用像 headers() 这样的运行时 API 时,预渲染终止。

app/api/user-agent/route.ts
1
2
3
4
5
6
7
8
import { headers } from 'next/headers'

export async function GET() {
  const headersList = await headers()
  const userAgent = headersList.get('user-agent')

  return Response.json({ userAgent })
}

扩展

如果 GET 处理程序访问网络请求、数据库查询、异步文件系统操作、请求对象属性(如 req.urlrequest.headersrequest.cookiesrequest.body)、运行时 API(如 cookies()headers()connection() 或非确定性操作),预渲染就会停止。

缓存示例:访问动态数据(数据库查询),但使用 use cache 对其进行缓存,从而允许将其包含在预渲染响应中。

app/api/products/route.ts
import { cacheLife } from 'next/cache'

export async function GET() {
  const products = await getProducts()
  return Response.json(products)
}

async function getProducts() {
  'use cache'
  cacheLife('hours')

  return await db.query('SELECT * FROM products')
}

扩展

use cache不能直接在路由处理器主体内部使用;将其提取到辅助函数中。当新请求到达时,缓存的响应会根据cacheLife 重新验证。

5. 特殊路由处理

特殊路由处理程序(例如 sitemap.tsopengraph-image.tsxicon.tsx )以及其他元数据文件默认保持静态,除非它们使用动态 API 或动态配置选项。

6. 路由解析

您可以将route视为最低级别的路由原语。

  • 它们不参与布局或客户端导航(例如 page)。
  • 不能有与 page.js 位于同一路由的 route.js 文件。
页面 路由 结果
app/page.jsapp/page.js app/route.jsapp/route.js 冲突
app/page.jsapp/page.js app/api/route.jsapp/api/route.js 有效
app/[user]/page.jsapp/[user]/page.js app/api/route.jsapp/api/route.js 有效

每个 route.jspage.js 文件都会接管该路由的所有 HTTP 方法。

app/page.ts
1
2
3
4
5
6
7
export default function Page() {
  return <h1>Hello, Next.js!</h1>
}

// Conflict
// `app/route.ts`
export async function POST(request: Request) {}

详细了解路由处理程序如何补充您的前端应用程序,或探索路由处理程序 API 参考。

7. 路由上下文助手

在 TypeScript 中,您可以使用全局可用的 RouteContext 帮助器输入路由处理程序的 context 参数:

app/user/[id]/route.ts
1
2
3
4
5
6
import type { NextRequest } from 'next/server'

export async function GET(_req: NextRequest, ctx: RouteContext<'/users/[id]'>) {
  const { id } = await ctx.params
  return Response.json({ id })
}

扩展

类型是 next devnext buildnext typegen 期间生成的。