文件命名约定
发现机制是自动的。DocfyModule 通过 Node 的模块缓存定位每个控制器的源文件。
约定
发现机制是自动的。DocfyModule 通过 Node 的模块缓存定位每个控制器的源文件,并解析出对应的 companion 路径:这在 ts-node(开发环境)和编译后的 dist/(生产环境)下行为完全一致。
| 控制器文件 | Companion 文件 |
|---|---|
users.controller.ts | users.controller.docs.ts |
users.controller.js | users.controller.docs.js |
Barrel 重导出
如果你的控制器同时也从一个 barrel index.ts 中导出,确保这个类是直接从它自己的模块文件导出的。nestjs-docfy 优先选择 .controller.ts,而不是 barrel 文件。
webpack: true 构建模式
如果你的 nest-cli.json 在 compilerOptions 下设置了 "webpack": true(这是官方文档为多应用 monorepo 推荐的默认配置),DocfyModule 的 运行时 管线(也就是上面描述的 @WithDocs() + require.cache 发现机制)就不会生效,而且没有任何配置能让它生效。这是架构层面的限制:
- Webpack 会把每个模块内联进一个单独的 bundle 文件,从不会像每个原始源文件对应一条记录那样填充 Node 的
require.cache,而发现机制正是依赖这一点。你会看到每个带@WithDocs()的控制器都报Could not locate source file for X。 - 即便绕开了这个查找问题(比如从 bundle 的 source map 里还原出原始路径,跳过
require.cache),还有第二道无法回避的障碍:从 bundle 外部 require() 加载的 docs 文件,会创建一个和运行中的应用实际使用的类在结构上完全不同的类对象。装饰这份全新的副本,对SwaggerModule.createDocument()真正输出的文档没有任何影响,而且这一切都是静默发生的,不会报任何错误。 - 唯一的绕开方式是让控制器文件本身去导入它的
.docs.tscompanion(强制 webpack 把两者打包在一起),但这样一来就违背了这个约定存在的全部意义:控制器和文档之间零耦合。
如何仍然拿到完整文档
CLI 插件(推荐):在 nest-cli.json 的 compilerOptions.plugins 中注册 nestjs-docfy,并在 SwaggerModule.createDocument() 之后立刻调用 applyDocfyMetadata()。在每次构建时自动地从根本上解决这个问题。见 CLI 插件。
如果不想加编译器插件,可以用 Use patch-spec 作为手动的、由 CI 驱动的替代方案。见 patch-spec:手动替代方案。或者彻底关闭 webpack 打包:在 nest-cli.json 中移除 "webpack": true(或者设为 false)。在默认基于 tsc 的编译模式下,每个源文件都会编译成自己独立的 .js,所以 require.cache 天然就是每个文件一条记录,DocfyModule 的运行时发现机制不需要任何改动就能正常工作。