Nextjs15 构建API端点

在 Next.js 15 中,API Router 已经不再是推荐的方式来构建 API 端点,而是被 App Router 中的 Route Handlers(路由处理器) 所取代。Next.js 15 鼓励开发者逐步从 Pages Router 迁移到 App Router,并使用 Route Handlers 来处理 API 请求,因为它们提供了更现代、更灵活的方式来构建服务器端逻辑。下面将详细介绍 Next.js 15 中 API Router 的作用、如何使用 Route Handlers 替代 API Router,以及相关的使用方法和注意事项。


1. API Router 的作用(Pages Router 中的传统方式)

在 Next.js 的 Pages Router(即 pages 目录)中,API Router 是一种用于构建服务器端 API 端点的机制。它的核心作用是允许开发者在 Next.js 应用中创建 RESTful API 或其他类型的服务器端接口,而无需额外搭建独立的 backend 服务。以下是 API Router 的主要作用:

  • 创建 API 端点 :通过在 pages/api 目录下创建文件(如 pages/api/hello.js),可以快速定义 /api/hello 这样的 API 端点。这些文件会被 Next.js 自动映射为服务器端 API,而不是前端页面。
  • 服务器端逻辑:API Router 运行在服务器端,适合处理数据库操作、外部 API 调用、身份验证等逻辑,不会增加客户端 bundle 大小。
  • 支持多种 HTTP 方法:可以处理 GET、POST、PUT、DELETE 等 HTTP 请求,适合构建 RESTful API。
  • 集成性强:与 Next.js 的其他功能(如 SSR、SSG)无缝集成,适合全栈开发。
  • CORS 和安全:API Router 默认是同源请求,开发者可以通过自定义 CORS 标头支持跨域请求。

然而,在 Next.js 15 中,官方推荐逐步采用 App RouterRoute Handlers 来替代 API Router,因为 Route Handlers 基于 Web 标准的 Request 和 Response API,提供了更高的灵活性和性能优化。


2. App Router 中的 Route Handlers(API Router 的替代方案)

在 Next.js 15 的 App Router(即 app 目录)中,Route Handlers 是 API Router 的现代替代方案。它们的作用与 API Router 类似,但有以下改进:

  • 基于 Web 标准:使用标准的 Request 和 Response 对象,兼容 Node.js 和 Edge Runtime。
  • 更灵活的路由:支持嵌套路由、动态路由和更复杂的路由模式。
  • 无 bodyParser 配置:无需像 API Router 那样手动配置 bodyParser,简化了开发流程。
  • 支持流式响应:Route Handlers 天然支持流式响应(Streaming),适合实时数据传输。
  • 缓存控制:Next.js 15 默认不缓存 GET 请求的 Route Handlers,但可以通过配置(如 export const dynamic = 'force-static')启用缓存。

Route Handlers 的作用

Route Handlers 用于为特定路由定义自定义的服务器端请求处理逻辑,常见用途包括:

  • 构建 RESTful API:处理 CRUD 操作(创建、读取、更新、删除)。
  • 处理 Webhook:接收来自第三方服务的请求(如 GitHub Webhook)。
  • 动态数据处理:从数据库或外部 API 获取数据并返回 JSON 响应。
  • 身份验证:实现登录、注销等功能。
  • 文件上传/下载:处理文件流或二进制数据。

3. 如何使用 Route Handlers

以下是详细的使用方法,涵盖创建、配置和高级用例。

3.1 创建 Route Handlers

  1. 文件结构

    • 在 app 目录下创建 route.js 或 route.ts 文件。例如,app/api/hello/route.ts 会映射到 /api/hello 端点。
    • Route Handlers 必须定义在 route.js 文件中,不能与 page.js 文件在同一路由段级别共存。
  2. 基本示例: 创建一个简单的 GET 请求处理器:

typescript 复制代码
// app/api/hello/route.ts
 export async function GET(request: Request) {
   return new Response(JSON.stringify({ message: "Hello from Next.js!" }), {
     status: 200,
     headers: { "Content-Type": "application/json" },
   });
 }
 

访问 http://localhost:3000/api/hello 将返回:{ "message": "Hello from Next.js!" }

  1. 支持多种 HTTP 方法 : Route Handlers 支持 GET、POST、PUT、PATCH、DELETE、HEAD 和 OPTIONS 方法。可以在同一个文件中定义多个方法:

    typescript 复制代码
    // app/api/users/route.ts import { NextResponse } from "next/server"; export async function GET(request: Request) { return NextResponse.json({ message: "Get all users" }, { status: 200 }); } export async function POST(request: Request) { const body = await request.json(); return NextResponse.json({ message: "User created", data: body }, { status: 201 }); } export async function DELETE(request: Request) { return NextResponse.json({ message: "User deleted" }, { status: 200 }); }`
    
    -   GET 请求:curl http://localhost:3000/api/users
    -   POST 请求:curl -X POST -H "Content-Type: application/json" -d '{"name":"John"}' http://localhost:3000/api/users
    -   DELETE 请求:curl -X DELETE http://localhost:3000/api/users

3.2 动态路由

Route Handlers 支持动态路由,通过在文件夹名称中使用方括号([])实现。例如:

typescript 复制代码
// app/api/users/[id]/route.ts export async function GET(request: Request, { params }: { params: { id: string } }) { const { id } = params; return NextResponse.json({ message: `Get user with ID: ${id}` }); }

访问 http://localhost:3000/api/users/123 将返回:{ "message": "Get user with ID: 123" }

3.3 处理请求体

Route Handlers 直接支持解析请求体,无需额外的 bodyParser 配置。例如:

typescript 复制代码
// app/api/submit/route.ts export async function POST(request: Request) { try { const data = await request.json(); return NextResponse.json({ message: "Data received", data }, { status: 200 }); } catch (error) { return NextResponse.json({ error: "Invalid JSON" }, { status: 400 }); } }

发送 POST 请求:

curl -X POST -H "Content-Type: application/json" -d '{"name":"Alice"}' http://localhost:3000/api/submit

返回:

{ "message": "Data received", "data": { "name": "Alice" } }

3.4 配置 CORS

Route Handlers 默认是同源请求。要支持跨域请求(CORS),可以手动设置响应头:

typescript 复制代码
// app/api/cors/route.ts export async function GET(request: Request) { return new Response(JSON.stringify({ message: "CORS enabled" }), { status: 200, headers: { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS", "Access-Control-Allow-Headers": "Content-Type, Authorization", }, }); } // 处理 OPTIONS 请求(CORS 预检请求) export async function OPTIONS() { return new Response(null, { status: 204, headers: { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS", "Access-Control-Allow-Headers": "Content-Type, Authorization", }, }); }

或者,可以在 next.config.js 中全局配置 CORS:

javascript 复制代码
// next.config.js module.exports = { async headers() { return [ { source: "/api/:path*", headers: [ { key: "Access-Control-Allow-Origin", value: "*" }, { key: "Access-Control-Allow-Methods", value: "GET,POST,PUT,DELETE,OPTIONS" }, { key: "Access-Control-Allow-Headers", value: "Content-Type, Authorization" }, ], }, ]; }, };

3.5 缓存控制

在 Next.js 15 中,GET 请求的 Route Handlers 默认不缓存(与 Next.js 14 不同)。如果需要启用缓存,可以使用以下配置:

typescript 复制代码
// app/api/data/route.ts export const dynamic = "force-static"; export async function GET() { const res = await fetch("https://api.example.com/data"); const data = await res.json(); return NextResponse.json({ data }); }
  • dynamic = 'force-static':强制将 GET 请求的响应缓存为静态内容。

  • 其他选项:

    • dynamic = 'force-dynamic':强制动态渲染,禁用缓存。
    • dynamic = 'auto'(默认):根据内容动态决定是否缓存。

3.6 流式响应

Route Handlers 支持流式响应,适合处理大文件或实时数据:

typescript 复制代码
// app/api/stream/route.ts export async function GET() { const stream = new ReadableStream({ async start(controller) { controller.enqueue(new TextEncoder().encode("Streaming started...\n")); await new Promise((resolve) => setTimeout(resolve, 1000)); controller.enqueue(new TextEncoder().encode("More data...\n")); controller.close(); }, }); return new Response(stream, { headers: { "Content-Type": "text/plain" }, }); }

访问 /api/stream 将逐步接收数据流。

3.7 身份验证示例

以下是一个使用 Route Handlers 实现简单登录 API 的示例:

typescript 复制代码
// app/api/login/route.ts import { NextResponse } from "next/server"; import jwt from "jsonwebtoken"; export async function POST(request: Request) { try { const { username, password } = await request.json(); // 模拟验证逻辑 if (username === "admin" && password === "password") { const token = jwt.sign({ username }, process.env.JWT_SECRET || "secret", { expiresIn: "1h", }); return NextResponse.json({ token }, { status: 200 }); } return NextResponse.json({ error: "Invalid credentials" }, { status: 401 }); } catch (error) { return NextResponse.json({ error: "Server error" }, { status: 500 }); } }

安装依赖: npm install jsonwebtoken

设置环境变量(.env.local):JWT_SECRET=your-secret-key

发送 POST 请求:

curl -X POST -H "Content-Type: application/json" -d '{"username":"admin","password":"password"}' http://localhost:3000/api/login

返回:

{ "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." }


4. API Router vs Route Handlers

以下是 Pages Router 的 API Router 和 App Router 的 Route Handlers 的对比:

特性 API Router (Pages Router) Route Handlers (App Router)
目录结构 pages/api app/api/.../route.js
API 风格 基于 NextApiRequest 和 NextApiResponse 基于 Web 标准的 Request 和 Response
运行时支持 仅 Node.js 支持 Node.js 和 Edge Runtime
Body 解析 需要配置 bodyParser 自动支持,无需额外配置
CORS 配置 手动设置或使用第三方库 直接在响应头或 next.config.js 中配置
流式响应 有限支持 原生支持流式响应
缓存默认行为 取决于配置 Next.js 15 默认不缓存 GET 请求
动态路由 支持 [id].js 和 [...slug].js 支持 [id]/route.js 和 [...slug]/route.js
与服务器组件集成 无直接集成 与服务器组件无缝集成

5. 迁移建议

如果你的项目仍在使用 Pages Router 的 API Router,Next.js 15 支持向后兼容 React 18 和 Pages Router,但官方强烈建议迁移到 App Router 和 Route Handlers。迁移步骤如下:

  1. 创建 app 目录:在项目根目录下创建 app 目录。

  2. 迁移 API 端点

    • 将 pages/api/hello.js 迁移到 app/api/hello/route.js。
    • 将 NextApiRequest 和 NextApiResponse 替换为 Request 和 Response 或 NextResponse。
  3. 更新逻辑

    • 移除 bodyParser 配置,直接使用 request.json() 或 request.text()。
    • 根据需要调整 CORS 和缓存配置。
  4. 使用 Codemods:Next.js 15 提供了自动化工具(codemod)来帮助迁移:

    npx @next/codemod

    运行后选择适当的迁移选项。


6. 注意事项

  • Edge Runtime:如果需要使用 Edge Runtime(例如 Vercel 的边缘网络),确保 Route Handlers 不依赖 Node.js 特定的 API(如 fs)。
  • 与 page.js 冲突:route.js 和 page.js 不能在同一路由段级别共存,否则会抛出错误。
  • 405 错误:如果客户端请求了未定义的 HTTP 方法(如在只有 GET 的 Route Handler 中请求 POST),Next.js 会自动返回 405 Method Not Allowed。
  • 安全性:避免直接将用户输入传递到 router.push 或 router.replace,以防止 XSS 攻击。

7. 总结

在 Next.js 15 中,API Router(Pages Router)仍然可用,但官方推荐使用 App Router 的 Route Handlers 来构建 API 端点。Route Handlers 提供了更现代的 API 设计、更好的性能优化和与服务器组件的集成。开发者可以通过简单的文件结构(如 app/api/.../route.ts)快速创建 RESTful API,支持动态路由、CORS、流式响应等功能。

相关推荐
一 乐41 分钟前
民宿|基于java的民宿推荐系统(源码+数据库+文档)
java·前端·数据库·vue.js·论文·源码
testleaf1 小时前
前端面经整理【1】
前端·面试
好了来看下一题1 小时前
使用 React+Vite+Electron 搭建桌面应用
前端·react.js·electron
啃火龙果的兔子1 小时前
前端八股文-react篇
前端·react.js·前端框架
小前端大牛马1 小时前
react中hook和高阶组件的选型
前端·javascript·vue.js
刺客-Andy1 小时前
React第六十二节 Router中 createStaticRouter 的使用详解
前端·javascript·react.js
萌萌哒草头将军3 小时前
🚀🚀🚀VSCode 发布 1.101 版本,Copilot 更全能!
前端·vue.js·react.js
GIS之路3 小时前
OpenLayers 图层叠加控制
前端·信息可视化
90后的晨仔4 小时前
ArkTS 语言中的number和Number区别是什么?
前端·harmonyos
菜鸡爱上编程4 小时前
React16,17,18,19更新对比
前端·javascript·reactjs·react