NextJs的后端目录结构说明
Table of Contents
以下是 Next.js 项目中后端 API 的目录结构及文件说明(涵盖 App Router 和 Pages Router 两种模式)。根据最新实践,推荐优先使用 App Router 的 API 路由设计
目录结构(App Router 模式)
my-next-app/
├── app/
│ ├── api/ # API 路由目录(核心目录)
│ │ ├── users/ # 用户相关 API 端点
│ │ │ ├── route.ts # `/api/users` 的路由处理
│ │ │ └── [id]/ # 动态路由(如 `/api/users/123`)
│ │ │ └── route.ts
│ │ ├── products/ # 商品相关 API
│ │ │ └── route.ts
│ │ └── auth/ # 认证相关 API
│ │ └── route.ts
├── lib/
│ ├── db.ts # 数据库连接工具
│ └── api-utils.ts # API 通用工具函数
├── middleware.ts # 全局中间件(如身份验证)
└── ...
关键文件说明(App Router)
1. app/api/[path]/route.ts
-
作用:定义 API 端点,支持
GET
/POST
/PUT
/DELETE
等方法。 -
文件命名规则:必须为
route.ts
(或route.js
)。 -
示例代码:
// app/api/users/route.ts import { NextResponse } from 'next/server'; import { db } from '@/lib/db'; // GET /api/users export async function GET() { const users = await db.user.findMany(); return NextResponse.json(users); } // POST /api/users export async function POST(request: Request) { const data = await request.json(); const newUser = await db.user.create({ data }); return NextResponse.json(newUser, { status: 201 }); }
2. 动态路由 app/api/users/[id]/route.ts
- 作用:处理带参数的请求(如
/api/users/123
)。 - 参数获取:
export async function GET( request: Request, { params }: { params: { id: string } } ) { const userId = params.id; // '123' // ... }
目录结构(Pages Router 模式 - 旧版)
my-next-app/
├── pages/
│ └── api/ # API 路由目录
│ ├── users.ts # `/api/users`
│ └── products/
│ ├── index.ts # `/api/products`
│ └── [id].ts # `/api/products/123`
└── ...
关键文件说明(Pages Router)
1. pages/api/[path].ts
-
作用:通过默认导出的函数处理请求。
-
示例代码:
// pages/api/users.ts import { NextApiRequest, NextApiResponse } from 'next'; import { db } from '@/lib/db'; export default async function handler( req: NextApiRequest, res: NextApiResponse ) { if (req.method === 'GET') { const users = await db.user.findMany(); res.status(200).json(users); } else { res.setHeader('Allow', ['GET']); res.status(405).end('Method Not Allowed'); } }
通用最佳实践
1. 分层架构
- 推荐结构:
app/ └── api/ └── users/ ├── route.ts # 路由入口 ├── controller.ts # 业务逻辑 ├── schema.ts # 请求验证(如 Zod) └── types.ts # 类型定义
2. 请求验证
-
使用 Zod 或 Yup:
// app/api/users/route.ts import { z } from 'zod'; const createUserSchema = z.object({ name: z.string().min(2), email: z.string().email(), }); export async function POST(request: Request) { const body = await request.json(); const validation = createUserSchema.safeParse(body); if (!validation.success) { return NextResponse.json(validation.error.errors, { status: 400 }); } // 处理合法请求... }
3. 错误处理
-
统一错误格式:
// lib/api-utils.ts export class APIError extends Error { constructor( public statusCode: number, public message: string, public details?: any ) { super(message); } } // 在路由中使用 export async function GET() { try { // ... } catch (err) { if (err instanceof APIError) { return NextResponse.json( { error: err.message, details: err.details }, { status: err.statusCode } ); } return NextResponse.json( { error: 'Internal Server Error' }, { status: 500 } ); } }
中间件集成
1. 全局中间件 (middleware.ts
)
-
作用:处理跨路由的通用逻辑(如身份验证、CORS)。
-
示例(身份验证):
// middleware.ts import { NextResponse } from 'next/server'; export function middleware(request: NextRequest) { const token = request.cookies.get('authToken'); const isAPIRoute = request.nextUrl.pathname.startsWith('/api'); // 拦截未授权的 API 请求 if (isAPIRoute && !token) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } return NextResponse.next(); }
2. 路由级中间件
-
自定义中间件链:
// app/api/users/route.ts import { withAuth } from '@/lib/middlewares'; // 组合中间件 const handler = async (request: Request) => { // 主逻辑 }; export const GET = withAuth(handler);
环境变量管理
-
敏感信息(如数据库密码)存储在
.env.local
:# .env.local DATABASE_URL="postgresql://user:password@localhost:5432/mydb"
-
在 API 中访问:
// lib/db.ts import { Pool } from 'pg'; const pool = new Pool({ connectionString: process.env.DATABASE_URL, });
常用工具推荐
- 数据库 ORM:Prisma、Drizzle
- 请求验证:Zod、Yup
- HTTP 客户端:
fetch
(内置)、axios - 身份验证:NextAuth.js、Clerk
- API 文档:Swagger UI、Next.js + OpenAPI
完整示例流程
请求:POST /api/users
// app/api/users/route.ts
export async function POST(request: Request) {
// 1. 验证请求体
const body = await request.json();
const validation = createUserSchema.safeParse(body);
if (!validation.success) { /* 返回 400 错误 */ }
// 2. 数据库操作
const newUser = await db.user.create({ data: validation.data });
// 3. 返回响应
return NextResponse.json(newUser, { status: 201 });
}
总结
Next.js 的 API 路由设计具有以下特点:
- 无服务器架构:自动处理服务器部署(Vercel 或其他平台)
- 灵活路由:支持动态参数、嵌套路由
- 中间件支持:全局或局部拦截请求
- 类型安全:与 TypeScript 深度集成
- 无缝扩展:可连接数据库、第三方服务
无论是构建简单的 MVP 还是复杂的企业级 API,这种结构都能提供清晰的代码组织和可维护性。
使用 mongodb.com 提供的免费500M mongodb 服务,结果死活连不上。改为用 supabase 的 Postgres 了
明天了解一下 mongodb 和 postgresql 的对比,它们各自的适用场景是怎样的