Skip to content

在 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);
}

实现步骤

  1. 创建正确目录结构

    app/
    └── api/
        └── accounts/
            └── login/
                └── route.ts  // 或 route.js
  2. 导出 HTTP 方法处理函数(支持 GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS

  3. 访问地址
    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

最佳实践建议

  1. 优先选择 app 路由 - 面向未来的新标准,支持流式响应、ISR 等现代特性
  2. 命名规范:必须使用 route.ts(TS)或 route.js(JS)作为文件名
  3. 动态路由:支持通过 [param] 语法创建动态路由
    folder
    app/api/user/[id]/route.ts
  4. 中间件集成:在 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*',
};

常见错误排查

  1. 无效路径:确认目录结构为 app/api/[端名]/route.ts
  2. 缺少导出方法:确保导出了对应的 HTTP 方法函数(如 export function GET
  3. 组件冲突:同一目录中 route.jspage.js 不能共存
  4. 版本兼容:检查 Next.js ≥13.2

注意

apppages 同时存在相同路由时,app 目录优先级更高。推荐项目统一选择一种路由体系

通过遵循这些规范,开发者可充分利用 Next.js 现代 API 路由的优势,构建更高效的应用架构。