swagger-jsdoc vs swagger-ui-express
在 Node.js 中构建和展示 API 文档的架构方案
swagger-jsdocswagger-ui-express

在 Node.js 中构建和展示 API 文档的架构方案

swagger-jsdoc 和 swagger-ui-express 是 Node.js 生态中用于处理 OpenAPI (Swagger) 规范的两个核心互补库,但它们解决的问题截然不同。swagger-jsdoc 专注于生成:它通过解析代码中的 JSDoc 注释,自动构建符合 OpenAPI 标准的 JSON/YAML 定义文件,实现了“文档即代码”的理念。swagger-ui-express 专注于展示:它是一个 Express 中间件,负责接收现有的 OpenAPI 定义对象,并将其渲染为交互式的 Swagger UI 前端界面。在实际工程中,它们通常配合使用:前者负责从源码提取元数据生成规范,后者负责将该规范可视化供开发者测试和查阅。

npm下载趋势

3 年

GitHub Stars 排名

统计详情

npm包名称
下载量
Stars
大小
Issues
发布时间
License
swagger-jsdoc01,788710 kB433 个月前MIT
swagger-ui-express01,49724 kB542 年前MIT

swagger-jsdoc vs swagger-ui-express: 文档生成与可视化的分工协作

在 Node.js后端开发中,维护高质量的 API 文档至关重要。swagger-jsdoc 和 swagger-ui-express 经常被一起提及,因为它们共同构成了一套完整的文档解决方案。然而,从架构角度看,它们处于文档生命周期的不同阶段:一个是生产者(生成规范),一个是消费者(渲染界面)。理解这种分工对于构建可维护的文档系统非常关键。

🏗️ 核心职责:生成定义 vs 渲染界面

swagger-jsdoc 的角色是解析与生成。它扫描你的源代码,提取 JSDoc 注释,并将其转换为标准的 OpenAPI (Swagger) JSON 对象。它不关心这个对象最终如何被展示,只关心生成的规范是否准确。

// 使用 swagger-jsdoc 生成规范对象
const swaggerJsdoc = require('swagger-jsdoc');

const options = {
  definition: {
    openapi: '3.0.0',
    info: { title: 'My API', version: '1.0.0' },
  },
  apis: ['./routes/*.js'], // 指定包含注释的文件路径
};

// 输出是一个纯粹的 JSON 对象,没有 UI 功能
const swaggerSpec = swaggerJsdoc(options);
console.log(typeof swaggerSpec); // 'object'

swagger-ui-express 的角色是服务与渲染。它接收一个已经存在的 OpenAPI JSON 对象,并通过 Express 中间件的形式,在特定路由下提供 Swagger UI 的静态资源和逻辑。

// 使用 swagger-ui-express 渲染界面
const swaggerUi = require('swagger-ui-express');
const express = require('express');
const app = express();

// 假设 swaggerSpec 已经由其他工具生成
const swaggerSpec = { /* ... OpenAPI JSON ... */ };

// 挂载 UI 到 /api-docs 路由
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec));

📝 文档编写方式:注释驱动 vs 文件驱动

这两个包的选择往往决定了你编写文档的方式。

swagger-jsdoc 强制推行注释驱动开发 (Annotation-Driven)。你将文档直接写在业务逻辑旁边。这保证了代码与文档的强一致性,但要求团队成员严格遵守 JSDoc 语法。

// 在路由文件中直接编写文档
/**
 * @swagger
 * /users:
 *   get:
 *     summary: 获取用户列表
 *     responses:
 *       200:
 *         description: 成功返回用户数组
 */
router.get('/users', (req, res) => {
  // 业务逻辑
});

swagger-ui-express 本身不限制文档来源,但它通常配合文件驱动 (File-Driven) 或上述的生成结果使用。如果你不使用 swagger-jsdoc,你可能需要手动维护一个巨大的 swagger.json 文件。swagger-ui-express 只是忠实地展示这个文件的内容。

// 手动加载静态 JSON 文件配合 swagger-ui-express
const swaggerDocument = require('./swagger-output.json'); 

app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));

⚙️ 配置复杂度与灵活性

swagger-jsdoc 需要配置解析规则。你需要定义哪些文件被扫描,以及如何映射注释标签到 OpenAPI 结构。如果项目结构复杂(如多层嵌套的 TypeScript 文件),配置正则匹配规则可能会变得繁琐。

// 复杂的 apis 匹配配置
const options = {
  definition: { /* ... */ },
  apis: [
    './src/routes/*.js',
    './src/models/*.js',
    './src/schemas/*.yaml' // 支持混合模式
  ],
};

swagger-ui-express 的配置非常直观,主要集中在 UI 的自定义上(如自定义 CSS、初始化参数)。它不关心数据来源的复杂性,只要传入的是一个合法的 OpenAPI 对象即可。

// 自定义 UI 选项
const options = {
  explorer: true, // 允许加载外部 URL
  customCss: '.swagger-ui .topbar { display: none }',
  swaggerOptions: { validatorUrl: null }
};

app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec, options));

🔄 典型集成模式:两者结合

在大多数专业场景中,我们不会二选一,而是将它们串联起来。swagger-jsdoc 作为构建时或启动时的生成器,swagger-ui-express 作为运行时的展示器。

const express = require('express');
const swaggerJsdoc = require('swagger-jsdoc');
const swaggerUi = require('swagger-ui-express');

const app = express();

// 1. 生成规范
const specs = swaggerJsdoc({
  definition: {
    openapi: '3.0.0',
    info: { title: 'Combined Example', version: '1.0.0' },
  },
  apis: ['./routes/*.js'],
});

// 2. 提供规范 JSON (可选,方便其他服务抓取)
app.get('/swagger.json', (req, res) => {
  res.json(specs);
});

// 3. 提供 UI 界面
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs));

app.listen(3000);

🚫 常见误区与限制

误区 1:认为 swagger-ui-express 能自动生成文档。 很多开发者安装了 swagger-ui-express 却发现界面是空的或者报错。这是因为它本身不具备解析代码注释的能力。你必须先有“数据”(OpenAPI 对象),它才能“画图”。

误区 2:过度依赖 swagger-jsdoc 的复杂逻辑。 swagger-jsdoc 适合描述请求/响应结构,但不适合编写复杂的业务逻辑描述。如果在注释中写入过多的逻辑判断描述,会导致注释难以维护。此时应考虑将部分定义提取到独立的 YAML 文件中引用。

限制:TypeScript 支持。 swagger-jsdoc 原生主要针对 JavaScript 和 JSDoc。虽然在 TypeScript 项目中也能工作(因为 TS 兼容 JSDoc),但对于纯 TypeScript 类型系统的深度集成(如自动从 Interface 生成 Schema),它的支持不如一些专用的 TS 插件(如 tsoa 或 @nestjs/swagger)完善。如果项目是重度 TypeScript 类型驱动,需评估是否值得引入额外的类型解析配置。

📊 总结对比

特性swagger-jsdocswagger-ui-express
主要功能解析注释,生成 OpenAPI JSON 对象接收 JSON 对象,渲染 Swagger UI 页面
输入源源代码文件 (.js, .ts, .yaml)OpenAPI 规范对象 (JSON/Object)
输出物JavaScript Object (Swagger Spec)HTTP 路由 (HTML/CSS/JS)
文档维护方式代码注释 (JSDoc)无 (仅展示,依赖上游数据源)
是否包含 UI否是
典型依赖场景需要“文档即代码”的项目需要在线 API 调试界面的项目

💡 架构建议

如果你的团队正在从零开始构建 Node.js API:

  1. 必选组合:同时安装这两个包。它们是成本最低、上手最快的文档解决方案。
  2. 工作流:配置 swagger-jsdoc 扫描你的路由层,确保每个端点都有基本的 JSDoc 描述。然后在 Express 入口文件中挂载 swagger-ui-express。
  3. 进阶考量:随着项目规模扩大,如果发现 JSDoc 注释变得过于臃肿,或者 TypeScript 类型无法自动映射到 Swagger Schema,可以考虑迁移到基于装饰器的方案(如 NestJS 的 Swagger 模块)或代码优先(Code-First)的类型安全方案。但在标准的 Express 架构中,swagger-jsdoc + swagger-ui-express 依然是稳健的默认选择。

如何选择: swagger-jsdoc vs swagger-ui-express

  • swagger-jsdoc:

    当你希望避免维护独立的 YAML 文档文件,并倾向于将 API 文档直接写在路由处理函数或控制器旁边的 JSDoc 注释中时,应选择 swagger-jsdoc。它适合那些希望文档能随代码逻辑同步更新、减少上下文切换的团队。如果你的项目结构清晰,且团队熟悉 JSDoc 语法,它能显著降低文档过时的风险。但请注意,它只负责生成定义对象,不负责提供可视化界面。

  • swagger-ui-express:

    当你已经拥有了一个有效的 OpenAPI (Swagger) 定义对象(无论是手动编写的 YAML/JSON,还是由 swagger-jsdoc 等工具生成的),并需要在 Express 应用中快速提供一个可视化的 API 测试界面时,必须选择 swagger-ui-express。它是将静态文档定义转化为可交互前端页面的标准解决方案。如果你只需要生成 JSON 文件而不需要内置的 UI 服务,或者你使用的是 Koa/NestJS 等其他框架(需寻找对应 UI 中间件),则不需要此包。

swagger-jsdoc的README

swagger-jsdoc

This library reads your JSDoc-annotated source code and generates an OpenAPI (Swagger) specification.

npm Downloads CI

Getting started

Imagine having API files like these:

/**
 * @openapi
 * /:
 *   get:
 *     description: Welcome to swagger-jsdoc!
 *     responses:
 *       200:
 *         description: Returns a mysterious string.
 */
app.get('/', (req, res) => {
  res.send('Hello World!');
});

The library will take the contents of @openapi (or @swagger) with the following configuration:

const swaggerJsdoc = require('swagger-jsdoc');

const options = {
  definition: {
    openapi: '3.0.0',
    info: {
      title: 'Hello World',
      version: '1.0.0',
    },
  },
  apis: ['./src/routes*.js'], // files containing annotations as above
};

const openapiSpecification = swaggerJsdoc(options);

The resulting openapiSpecification will be a swagger tools-compatible (and validated) specification.

swagger-jsdoc example screenshot

System requirements

  • Node.js 20.x or higher

You are viewing swagger-jsdoc v6 which is published in CommonJS module system.

Installation

npm install swagger-jsdoc --save

Or

yarn add swagger-jsdoc

Supported specifications

  • OpenAPI 3.x
  • Swagger 2
  • AsyncAPI 2.0

Validation of swagger docs

By default swagger-jsdoc tries to parse all docs to it's best capabilities. If you'd like to you can instruct an Error to be thrown instead if validation failed by setting the options flag failOnErrors to true. This is for instance useful if you want to verify that your swagger docs validate using a unit test.

const swaggerJsdoc = require('swagger-jsdoc');

const options = {
  failOnErrors: true, // Whether or not to throw when parsing errors. Defaults to false.
  definition: {
    openapi: '3.0.0',
    info: {
      title: 'Hello World',
      version: '1.0.0',
    },
  },
  apis: ['./src/routes*.js'],
};

const openapiSpecification = swaggerJsdoc(options);

Documentation

Click on the version you are using for further details: