Next.js 13引入了一个新特性:Route Handlers。
这个特性为我们提供了一种在App Router中创建API端点的新方式。
如果你觉得自己已经很熟悉Next.js的API路由了,那么这篇文章可能会给你一些新的见解。
Route Handlers:Next.js API的新时代
Route Handlers是Next.js在app目录中处理API请求的方式。
它们使用了Web Request和Response APIs,这意味着你可以使用标准的Web API来处理请求和响应。
基本用法
在app目录中创建一个route.js(或route.ts)文件就可以定义一个Route Handler。例如:
// app/api/hello/route.ts
export async function GET(request: Request) {
return new Response('Hello, Next.js!')
}
这个简单的例子创建了一个响应GET请求的API端点。
支持的HTTP方法
Route Handlers支持所有主要的HTTP方法:GET, POST, PUT, PATCH, DELETE, HEAD, 和 OPTIONS。例如:
export async function GET(request: Request) {
// 处理GET请求
}
export async function POST(request: Request) {
// 处理POST请求
}
// 其他方法类似...
高级用法
1. 动态路由
Route Handlers支持动态路由,这让我们可以创建更灵活的API:
// app/api/user/[id]/route.ts
export async function GET(
request: Request,
{ params }: { params: { id: string } }
) {
const id = params.id
// 使用id获取用户数据
return new Response(`User id: ${id}`)
}
另外一个例子,可以获得嵌套参数:
export async function GET(
request: Request,
{ params }: { params: { slug: string } }
) {
const slug = params.slug // 'a', 'b', or 'c'
}
在官方文档上提到:
2. 查询参数处理
Next.js提供了便捷的方法来处理查询参数:
import { type NextRequest } from 'next/server'
export function GET(request: NextRequest) {
const searchParams = request.nextUrl.searchParams
const query = searchParams.get('query')
// 处理查询参数
}
3. 响应流
Route Handlers支持流式响应,这在处理大量数据或长时间运行的操作时非常有用:
function iteratorToStream(iterator) {
return new ReadableStream({
async pull(controller) {
const { value, done } = await iterator.next()
if (done) {
controller.close()
} else {
controller.enqueue(value)
}
},
})
}
export async function GET() {
const iterator = async function* () {
yield 'Hello'
await new Promise(resolve => setTimeout(resolve, 1000))
yield 'World'
}()
const stream = iteratorToStream(iterator)
return new Response(stream)
}
4. CORS处理
你可以直接在Route Handler中设置CORS头:
export async function GET(request: Request) {
return new Response('Hello, Next.js!', {
status: 200,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
},
})
}
5.文件上传
处理文件上传变得更加简单:
export async function POST(request: Request) {
const formData = await request.formData()
const file = formData.get('file')
// 处理文件上传
}
6.性能优化
Route Handlers默认是动态的,但你可以通过配置使它们变为静态:
export const dynamic = 'force-static'
export async function GET() {
// 这个处理器会被静态生成
}
route.js
在我们深入探讨 Route Handlers 的各种用法之后,让我们特别关注一下 route.js
文件本身。
这个特殊的文件在 Next.js 的 App Router 中扮演着关键角色,它不仅定义了 API 路由,还控制着路由的行为和性能特性。
route.js 的特殊性
route.js
是 Next.js 中的一个特殊文件,它专门用于创建 API 路由。与 page.js
不同,route.js
不会渲染 UI,而是专注于处理 HTTP 请求和响应。
重要的是要注意,在同一个路由段级别上,route.js
和 page.js
不能共存。
这是因为 Next.js 需要明确知道应该如何处理对该路由的请求 —— 是渲染一个页面还是处理一个 API 请求。
文件命名和位置
route.js
(或 route.ts
对于 TypeScript 项目)可以放置在 app
目录的任何嵌套层级中。例如:
app/api/route.js
app/dashboard/api/route.js
app/users/[id]/route.js
配置选项
route.js
文件支持多种配置选项,这些选项可以影响路由的行为和性能。以下是一些重要的配置选项:
export const dynamic = 'auto'
export const dynamicParams = true
export const revalidate = false
export const fetchCache = 'auto'
export const runtime = 'nodejs'
export const preferredRegion = 'auto'
让我们逐一解释这些选项:
dynamic
:控制路由的动态行为。可以设置为 ‘auto’、’force-dynamic’ 或 ‘force-static’。dynamicParams
:决定是否允许动态参数。revalidate
:设置重新验证的时间间隔(以秒为单位)。fetchCache
:控制 fetch 请求的缓存行为。runtime
:指定运行时环境,可以是 ‘nodejs’ 或 ‘edge’。preferredRegion
:指定首选的部署区域。
示例:配置静态路由
如果你想创建一个静态生成的 API 路由,可以这样配置:
// app/api/static-data/route.ts
export const dynamic = 'force-static'
export async function GET() {
const data = await fetchSomeData()
return Response.json(data)
}
这个配置会使 Next.js 在构建时生成这个 API 路由的响应,而不是在每次请求时动态生成。
注意事项
- 路由冲突:确保在同一路径下不会同时存在
route.js
和page.js
。 - HTTP 方法:只有你在
route.js
中明确定义的 HTTP 方法才会被处理。未定义的方法会返回 405 Method Not Allowed。 - TypeScript 支持:使用 TypeScript 时,你可以利用类型系统来增强代码的可靠性和可维护性。
最佳实践
- 合理使用静态生成:对于不经常变化的数据,使用静态生成可以显著提高性能。
- 适当设置缓存:根据你的数据更新频率,合理设置
revalidate
选项。 - 选择正确的运行时:根据你的需求选择 Node.js 或 Edge 运行时。Edge 运行时通常具有更低的冷启动时间,适合需要快速响应的场景。
- 利用动态导入:对于大型依赖,可以使用动态导入来优化加载时间。
希望这篇文章能帮助你更好地理解和使用Next.js的Route Handlers。Happy coding!