路由处理器(Route Handlers)允许你使用 Web Request 和 Response API 为给定路由创建自定义请求处理器。

须知:路由处理器仅在
app目录中可用。它们等同于pages目录中的 API 路由,这意味着你无需同时使用 API 路由和路由处理器。
路由处理器定义在 app 目录中的 route.js|ts 文件 中:
export async function GET(request: Request) {}export async function GET(request) {}路由处理器可以像 page.js 和 layout.js 文件一样,嵌套在 app 目录中的任何位置。但是,不能在与 page.js 相同的路由段级别上存在 route.js 文件。
支持以下 HTTP 方法:GET、POST、PUT、PATCH、DELETE、HEAD 和 OPTIONS。如果调用了不支持的方法,Next.js 将返回 405 Method Not Allowed 响应。
NextRequest 和 NextResponse API除了支持原生的 Request 和 Response API 外,Next.js 还通过 NextRequest 和 NextResponse 对它们进行了扩展,为高级用例提供了便利的辅助功能。
路由处理器默认不缓存。但是,你可以选择为 GET 方法启用缓存。其他支持的 HTTP 方法不会被缓存。要缓存 GET 方法,请在你的路由处理器文件中使用 路由配置选项,例如 export const dynamic = 'force-static'。
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 });
}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方法放在同一文件中,它们也不会被缓存。
当启用 缓存组件 时,GET 路由处理器遵循与应用程序中普通 UI 路由相同的模型。它们默认在请求时运行,当不访问动态或运行时数据时可以进行预渲染,并且你可以使用 use cache 将动态数据包含在静态响应中。
静态示例 - 不访问动态或运行时数据,因此将在构建时预渲染:
export async function GET() {
return Response.json({
projectName: "Next.js",
});
}动态示例 - 访问非确定性操作。在构建期间,当调用 Math.random() 时,预渲染会停止,推迟到请求时渲染:
export async function GET() {
return Response.json({
randomNumber: Math.random(),
});
}运行时数据示例 - 访问请求特定数据。当调用像 headers() 这样的运行时 API 时,预渲染会终止:
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.url、request.headers、request.cookies、request.body)、运行时 API(如cookies()、headers()、connection())或非确定性操作,预渲染将停止。
缓存示例 - 访问动态数据(数据库查询),但使用 use cache 进行缓存,使其能够包含在预渲染响应中:
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进行重新验证。
像 sitemap.ts、opengraph-image.tsx 和 icon.tsx 等特殊路由处理器,以及其他 元数据文件,除非使用动态 API 或动态配置选项,否则默认保持静态。
你可以将 route 视为最低级别的路由原语。
page 一样的客户端导航。page.js 相同的路由上存在 route.js 文件。| 页面 | 路由 | 结果 |
|---|---|---|
app/page.js | app/route.js | 冲突 |
app/page.js | app/api/route.js | 有效 |
app/[user]/page.js | app/api/route.js | 有效 |
每个 route.js 或 page.js 文件都会接管该路由的所有 HTTP 动词。
export default function Page() {
return <h1>Hello, Next.js!</h1>;
}
// Conflict
// `app/route.ts`
export async function POST(request: Request) {}export default function Page() {
return <h1>Hello, Next.js!</h1>;
}
// Conflict
// `app/route.js`
export async function POST(request) {}了解更多关于路由处理器如何 补充你的前端应用 的信息,或查阅路由处理器 API 参考。
在 TypeScript 中,你可以使用全局可用的 RouteContext 辅助函数来为路由处理器的 context 参数进行类型定义:
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 dev、next build或next typegen期间生成的。