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、流式响应等功能。

相关推荐
加班是不可能的,除非双倍日工资4 小时前
css预编译器实现星空背景图
前端·css·vue3
wyiyiyi4 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
gnip5 小时前
vite和webpack打包结构控制
前端·javascript
excel5 小时前
在二维 Canvas 中模拟三角形绕 X、Y 轴旋转
前端
阿华的代码王国5 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
一条上岸小咸鱼5 小时前
Kotlin 基本数据类型(三):Booleans、Characters
android·前端·kotlin
Jimmy5 小时前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程
ZXT6 小时前
promise & async await总结
前端
Jerry说前后端6 小时前
RecyclerView 性能优化:从原理到实践的深度优化方案
android·前端·性能优化
画个太阳作晴天6 小时前
A12预装app
linux·服务器·前端