⚠️ Alpha内测版本警告:此为早期内部构建版本,尚不完整且可能存在错误,欢迎大家提Issue反馈问题或建议
Skip to content

12.7.1 API 版本的规则——API 版本策略:URL/Header 版本控制

一句话破题

API 版本控制有三种主流方式:URL 路径、Query 参数、请求头——选择哪种取决于你的场景和团队偏好。

版本控制方式对比

方式示例优点缺点
URL 路径/api/v1/users直观、易缓存URL 变化大
Query 参数/api/users?version=1灵活容易被忽略
请求头Accept: application/vnd.api+json;version=1URL 干净不直观

URL 路径版本控制

最常见的方式,推荐用于大多数场景:

typescript
// app/api/v1/users/route.ts
export async function GET() {
  return Response.json({ version: 'v1', users: [] });
}

// app/api/v2/users/route.ts
export async function GET() {
  return Response.json({ 
    version: 'v2', 
    data: { users: [] },  // v2 改变了响应结构
    meta: { total: 0 },
  });
}

请求头版本控制

适合不想改变 URL 的场景:

typescript
// app/api/users/route.ts
export async function GET(req: Request) {
  const version = req.headers.get('X-API-Version') || '1';
  
  switch (version) {
    case '1':
      return Response.json({ users: [] });
    case '2':
      return Response.json({ data: { users: [] }, meta: {} });
    default:
      return Response.json({ error: '不支持的版本' }, { status: 400 });
  }
}

语义化版本

遵循 SemVer 规范:

主版本.次版本.修订号
  ^      ^      ^
  |      |      +--- 向后兼容的问题修复
  |      +---------- 向后兼容的新功能
  +----------------- 破坏性变更
typescript
// 版本比较工具
interface Version {
  major: number;
  minor: number;
  patch: number;
}

function parseVersion(version: string): Version {
  const [major, minor, patch] = version.split('.').map(Number);
  return { major, minor, patch };
}

function isCompatible(required: string, current: string): boolean {
  const req = parseVersion(required);
  const cur = parseVersion(current);
  
  // 主版本必须匹配
  if (req.major !== cur.major) return false;
  
  // 当前版本必须 >= 要求版本
  if (cur.minor < req.minor) return false;
  if (cur.minor === req.minor && cur.patch < req.patch) return false;
  
  return true;
}

Next.js 中的多版本 API

typescript
// lib/api-versions.ts
type Handler = (req: Request) => Promise<Response>;

const handlers: Record<string, Record<string, Handler>> = {
  'v1': {
    'GET /users': async () => Response.json({ users: [] }),
  },
  'v2': {
    'GET /users': async () => Response.json({ data: { users: [] } }),
  },
};

export function createVersionedHandler(path: string) {
  return async (req: Request) => {
    const version = req.headers.get('X-API-Version') || 'v2'; // 默认最新版本
    const method = req.method;
    const key = `${method} ${path}`;
    
    const handler = handlers[version]?.[key];
    if (!handler) {
      return Response.json({ error: '端点不存在' }, { status: 404 });
    }
    
    return handler(req);
  };
}

AI 协作指南

  • 核心意图:让 AI 帮你设计 API 版本策略。
  • 需求定义公式"请帮我设计一个 Next.js API 的版本控制方案,支持 URL 路径版本和请求头版本两种方式。"
  • 关键术语API 版本控制SemVer向后兼容破坏性变更

避坑指南

  • 从 v1 开始:不要用 v0,它暗示不稳定。
  • 文档要跟上:每个版本都需要独立的文档。
  • 设置默认版本:未指定版本时使用稳定版本(不一定是最新版)。