CLI 插件

针对 webpack: true 推荐的修复方式,在每次构建时自动生效,不需要额外记住一个单独的步骤。

这正是 @nestjs/swagger 自身 CLI 插件在 webpack: true 下工作所用的机制。这也是为什么即便在 webpack 构建下,也不需要在每个 DTO 属性上都加 @ApiProperty()。Nest CLI 会把一个 TypeScript 编译器插件钩子(compilerOptions.plugins)同时喂给 tsc 和 webpack(ts-loader)构建器,两者行为完全一致。

注册插件

nest-cli.json 中注册 nestjs-docfy

nest-cli.json
{
  "compilerOptions": {
    "webpack": true,
    "plugins": ["nestjs-docfy"]
  }
}
main.ts
import { applyDocfyMetadata } from 'nestjs-docfy';

const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api', app, applyDocfyMetadata(document));
OptionTypeDefaultDescription
metadataPathstringdocfy-metadata.json next to the running entry fileWhere to read the plugin-generated metadata from.
strictbooleanfalseThrow instead of warning when the metadata file is missing or invalid.

自动检测

忘记注册插件很容易,往往要等到构建出去了却没有文档才被发现,所以每次运行 generate 都会检查 nest-cli.json,在设置了 webpack: true 却没配插件时打印警告。传入 --register-plugin,让它替你修好这个问题,而不用手动编辑文件:

bash
npx nestjs-docfy generate --register-plugin

这是刻意做成 opt-in 的,因为有些团队会特意选择继续用 patch-spec,而不是加一个编译器插件,所以除非你明确要求,否则 generate 从不会修改 nest-cli.json。它会追加到任何已有的 compilerOptions.plugins 数组中(能识别字符串形式和对象形式两种已注册条目),并遵守 --dry-run

工作原理

nestjs-docfy 的插件不会重写任何装饰器语法,也完全不碰 AST。每次编译时,它都会重新跑一遍和 generate/check/patch-spec 已经在做的完全相同的静态分析(通过 ts-morph,针对源代码树,而不是 bundle),并把结果写进构建输出旁边的 docfy-metadata.json

然后,在 SwaggerModule.createDocument() 之后立刻,applyDocfyMetadata() 读取这个文件并把内容合并进去。这里没有涉及 require.cache,也没有 bundle 内类身份不一致的问题,因为它从来不需要运行中的应用来计算任何东西。

与 patch-spec 的对比

Manual, CI-driven alternative

如果你不想加编译器插件(比如构建管线不是 Nest CLI,或者对编译期间能运行什么有更严格的策略),patch-spec 可以针对一份已经构建好的文档手动计算出完全相同的补丁。在插件出现之前,这是唯一的选择,现在对一次性打补丁来说依然有用。