Koa.js API 文档自动生成与 Swagger 集成
API 文档概述
良好的 API 文档是提高开发效率、促进团队协作的关键。传统的手写文档方式存在更新不及时、格式不统一等问题。通过自动化工具,可以实现代码与文档的同步更新,确保文档的准确性和时效性。本文介绍 Koa.js 项目中 API 文档的自动生成方案,基于 Swagger/OpenAPI 规范实现。
技术选型
API 文档自动化技术栈:
| 工具/库 | 功能描述 | 特点 |
|---|---|---|
| koa-swagger-doctornpm | 从代码生成Swagger文档 | 零配置、注解驱动 |
| swagger-ui-express | 提供Swagger UI界面 | 可视化、在线测试 |
| @apidevtools/swagger-cli | 验证和合并OpenAPI文档 | CI/CD 集成 |
| openapi-schema-validator | OpenAPI 规范验证 | 保证文档质量 |
核心功能实现
1. 安装和基础配置
安装相关依赖:
npm install koa2-swagger-ui swagger-jsdoc // swagger-jsdoc: 根据 JSDoc 注释生成 Swagger 文档 // koa2-swagger-ui: 在 Koa 中集成 Swagger UI
// swagger.js - 文档配置
const swaggerJsdoc = require('swagger-jsdoc');
const options = {
definition: {
openapi: '3.0.0',
info: {
title: 'Koa.js REST API',
version: '1.0.0',
description: 'Koa.js RESTful API 文档',
contact: {
name: 'API Support',
email: 'support@example.com'
},
license: {
name: 'MIT',
url: 'https://opensource.org/licenses/MIT'
}
},
servers: [
{
url: 'http://localhost:3000',
description: '开发环境'
},
{
url: 'https://api.example.com',
description: '生产环境'
}
],
components: {
securitySchemes: {
bearerAuth: {
type: 'http',
scheme: 'bearer',
bearerFormat: 'JWT'
},
apiKey: {
type: 'apiKey',
in: 'header',
name: 'X-API-Key'
}
}
},
security: [{
bearerAuth: [],
apiKey: []
}]
},
apis: ['./routes/*.js', './controllers/*.js'] // 需要扫描的路由文件
};
const swaggerSpec = swaggerJsdoc(options);
module.exports = swaggerSpec;
2. 路由注解配置
在路由文件中使用 JSDoc 注解:
/**
* @swagger
* /api/users:
* get:
* summary: 获取用户列表
* description: 分页获取用户列表,支持过滤和排序
* tags:
* - 用户管理
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* default: 1
* description: 页码
* - in: query
* name: pageSize
* schema:
* type: integer
* default: 10
* description: 每页数量
* - in: query
* name: status
* schema:
* type: string
* enum: [active, inactive, all]
* default: active
* description: 用户状态过滤
* - in: query
* name: sort
* schema:
* type: string
* default: createdAt
* description: 排序字段
* responses:
* 200:
* description: 成功获取用户列表
* content:
* application/json:
* schema:
* type: object
* properties:
* code:
* type: integer
* example: 0
* message:
* type: string
* example: success
* data:
* type: object
* properties:
* list:
* type: array
* items:
* $ref: '#/components/schemas/User'
* pagination:
* $ref: '#/components/schemas/Pagination'
* 400:
* description: 请求参数错误
* 500:
* description: 服务器内部错误
*
* post:
* summary: 创建用户
* tags:
* - 用户管理
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/CreateUserRequest'
* responses:
* 201:
* description: 用户创建成功
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/UserResponse'
* 400:
* description: 请求参数错误
* 409:
* description: 用户已存在
*/
// 在路由处理函数中使用
router.get('/api/users', async (ctx) => {
const { page = 1, pageSize = 10, status = 'active', sort = 'createdAt' } = ctx.query;
const result = await userService.getUsers({
page: parseInt(page),
pageSize: parseInt(pageSize),
status,
sort
});
ctx.body = {
code: 0,
message: 'success',
data: result
};
});
router.post('/api/users', async (ctx) => {
const userData = ctx.request.body;
const user = await userService.createUser(userData);
ctx.status = 201;
ctx.body = {
code: 0,
message: 'success',
data: user
};
});
3. 数据模型注解
定义 Schema 数据模型:
/** * @swagger * components: * schemas: * User: * type: object * required: * - id * - username * - email * properties: * id: * type: string * format: uuid * description: 用户ID * username: * type: string * description: 用户名 * email: * type: string * format: email * description: 邮箱 * status: * type: string * enum: [active, inactive] * description: 用户状态 * role: * type: string * enum: [admin, user, guest] * description: 用户角色 * createdAt: * type: string * format: date-time * description: 创建时间 * updatedAt: * type: string * format: date-time * description: 更新时间 * example: * id: 550e8400-e29b-41d4-a716-446655440000 * username: john_doe * email: john@example.com * status: active * role: user * createdAt: 2025-01-01T00:00:00.000Z * * CreateUserRequest: * type: object * required: * - username * - email * - password * properties: * username: * type: string * minLength: 3 * maxLength: 20 * email: * type: string * format: email * password: * type: string * minLength: 6 * format: password * role: * type: string * enum: [admin, user, guest] * default: user * * Pagination: * type: object * properties: * page: * type: integer * pageSize: * type: integer * total: * type: integer * totalPages: * type: integer * * UserResponse: * type: object * properties: * code: * type: integer * example: 0 * message: * type: string * example: success * data: * $ref: '#/components/schemas/User' * * ErrorResponse: * type: object * properties: * code: * type: integer * example: 1 * message: * type: string * errors: * type: array * items: * type: object * properties: * field: * type: string * message: * type: string */
4. 集成 Swagger UI
在 Koa 中启用 Swagger UI:
// app.js
const Koa = require('koa');
const Router = require('koa-router');
const koaStatic = require('koa-static');
const path = require('path');
const swaggerJsdoc = require('swagger-jsdoc');
const { swaggerUi, swaggerSpec } = require('./swagger');
const app = new Koa();
const router = new Router();
// 静态文件服务( Swagger UI 资源)
app.use(koaStatic(path.join(__dirname, 'public')));
// API 路由
router.get('/api/users', userController.list);
router.post('/api/users', userController.create);
// ... 其他路由
// Swagger 文档 JSON 端点
router.get('/swagger.json', async (ctx) => {
ctx.body = swaggerSpec;
});
// Swagger UI 中间件
router.get('/docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec));
// API 文档页面(旧路径兼容)
router.get('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec));
app.use(router.routes());
app.use(router.allowedMethods());
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
console.log('Swagger docs: http://localhost:3000/docs');
});
// swagger.js - 导出 swagger-ui 中间件
const swaggerUi = require('swagger-ui-express');
const swaggerJsdoc = require('swagger-jsdoc');
// swaggerSpec 配置
const swaggerSpec = swaggerJsdoc({
definition: {
openapi: '3.0.0',
info: {
title: '我的Koa API',
version: '1.0.0',
description: 'API documentation'
},
servers: [
{ url: 'http://localhost:3000' }
]
},
apis: ['./routes/*.js']
});
module.exports = {
swaggerUi,
swaggerSpec
};
5. 高级:多版本 API 文档
支持 API 版本管理:
// 多版本 API 配置
const versions = {
'v1': {
swagger: swaggerJsdoc({
definition: {
openapi: '3.0.0',
info: {
title: '我的Koa API - v1',
version: '1.0.0',
description: '第一版API'
},
servers: [{ url: '/api/v1' }]
},
apis: ['./routes/v1/*.js']
}),
prefix: '/api/v1'
},
'v2': {
swagger: swaggerJsdoc({
definition: {
openapi: '3.0.0',
info: {
title: '我的Koa API - v2',
version: '2.0.0',
description: '第二版API,新增xxx功能'
},
servers: [{ url: '/api/v2' }]
},
apis: ['./routes/v2/*.js']
}),
prefix: '/api/v2'
}
};
// 版本选择 UI
const swaggerOptions = {
explorer: true,
swaggerOptions: {
urls: [
{
url: '/api/v1/swagger.json',
name: 'API v1.0'
},
{
url: '/api/v2/swagger.json',
name: 'API v2.0'
}
]
}
};
// 各版本文档路由
router.get('/api/v1/swagger.json', (ctx) => {
ctx.body = versions.v1.swagger;
});
router.get('/api/v2/swagger.json', (ctx) => {
ctx.body = versions.v2.swagger;
});
// Swagger UI(支持版本切换)
router.get('/docs', swaggerUi.serve, swaggerUi.setup(null, swaggerOptions));
6. CI/CD 集成
在持续集成中验证和发布文档:
// package.json 配置脚本
{
"scripts": {
"docs:validate": "swagger-cli validate ./swagger.json",
"docs:serve": "node scripts/serve-docs.js",
"docs:build": "rm -rf docs && swagger-cli bundle -r ./swagger.json -o docs/swagger.json"
}
}
# .gitlab-ci.yml 或 .github/workflows/api-docs.yml
stages:
- validate
- deploy
validate-api-docs:
stage: validate
script:
- npm install
- npm run docs:validate
only:
- merge_requests
- master
deploy-api-docs:
stage: deploy
script:
- npm run docs:build
# 部署到静态网站托管
- npx vercel deploy --prod --dir docs
only:
- master
when: manual
使用效果
自动生成文档的优势:
| 功能 | 描述 |
|---|---|
| 在线测试 | 可在 UI 中直接发送请求测试 API |
| 代码即文档 | 更新代码时自动更新文档 |
| 团队协作 | 前端可并行开发,减少沟通成本 |
| 自动化测试 | CI 中自动验证 API 规范 |
最佳实践
API 文档编写建议:
- 注释放规范:统一团队的 JSDoc 注解风格,形成文档规范
- 示例完整:为每个接口提供完整的请求/响应示例
- 错误码说明:详细列出可能返回的错误码及含义
- 版本管理:API 变更时及时更新版本号和文档
- CI 集成:将文档验证加入 CI 流程,防止不规范提交
总结
通过 Swagger/OpenAPI 规范和自动化工具,可以实现 API 文档与代码的同步更新,显著提高开发效率和 API 质量。建议将文档验证加入 CI/CD 流程,确保文档的准确性和规范性。