在 Next.js 应用目录中创建 API 路由
问题描述
Next.js 13 引入了创新的 app
目录架构(当时处于实验阶段),许多开发者遇到将传统 pages/api
路由迁移到新架构的挑战。具体表现为:
- 试图将
pages/api/accounts/login.js
迁移到app
目录 - 尝试路径
app/api/accounts/login/page.js
失败 - 访问
http://localhost:3000/api/accounts/login
时出现错误:Server Error Error: Cannot find module for page: /api/accounts/login
这些错误源于文件位置或命名与新架构不匹配,需要遵循新的路由规范。
TIP
Next.js 13.2+ 已将 app
目录路由提升为稳定特性,推荐新项目优先使用此架构
解决方案
路由处理器(Route Handlers)
从 Next.js 13.2 开始,通过 路由处理器(Route Handlers) 在 app 目录中创建 API 端点:
ts
import { NextResponse } from "next/server";
// 处理 POST 请求
export async function POST(req: Request) {
const body = await req.json();
// 身份验证逻辑
return NextResponse.json({ success: true });
}
// 处理 GET 请求
export async function GET() {
const data = fetchExternalData();
return NextResponse.json(data);
}
实现步骤
创建正确目录结构
app/ └── api/ └── accounts/ └── login/ └── route.ts // 或 route.js
导出 HTTP 方法处理函数(支持
GET
,POST
,PUT
,PATCH
,DELETE
,HEAD
,OPTIONS
)访问地址:
http://localhost:3000/api/accounts/login
传统方式对比(混合架构)
若需同时在 app 目录使用新路由且保留 pages API:
folder
src/
├── app/ // 新应用路由
└── pages/ // 传统页面路由
└── api/ // 原始API路由
└── accounts/
└── login.ts
pages API 示例:
ts
import type { NextApiRequest, NextApiResponse } from 'next';
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method === 'POST') {
res.status(200).json({ message: 'Success' });
} else {
res.setHeader('Allow', ['POST']);
res.status(405).end(`Method ${req.method} Not Allowed`);
}
}
重要区别
- app 路由:使用标准 Request/Response 对象 +
NextResponse.json()
- pages API:使用 Next 扩展的
NextApiRequest/NextApiResponse
最佳实践建议
- 优先选择 app 路由 - 面向未来的新标准,支持流式响应、ISR 等现代特性
- 命名规范:必须使用
route.ts
(TS)或route.js
(JS)作为文件名 - 动态路由:支持通过
[param]
语法创建动态路由folderapp/api/user/[id]/route.ts
- 中间件集成:在
app/
根目录创建middleware.ts
统一处理请求
ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
// 全局鉴权逻辑
if (!request.cookies.has('auth')) {
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next();
}
// 匹配规则:仅对API路由生效
export const config = {
matcher: '/api/:path*',
};
常见错误排查
- 无效路径:确认目录结构为
app/api/[端名]/route.ts
- 缺少导出方法:确保导出了对应的 HTTP 方法函数(如
export function GET
) - 组件冲突:同一目录中
route.js
和page.js
不能共存 - 版本兼容:检查 Next.js ≥13.2
注意
当 app
和 pages
同时存在相同路由时,app
目录优先级更高。推荐项目统一选择一种路由体系
通过遵循这些规范,开发者可充分利用 Next.js 现代 API 路由的优势,构建更高效的应用架构。