如何在NX构建的NestJS Monorepo中生成OpenAPI JSON文件
可行实现方案
针对NX构建输出单文件bundle的场景,以下两种方案都不需要把OpenAPI生成逻辑耦合到main.ts的服务启动流程里:
方案1:构建前直接运行TS源码生成(推荐)
这个方案不依赖构建后的产物,直接在构建阶段解析TS源码执行,完美适配NX的Monorepo依赖管理逻辑:
- 首先在对应NestJS应用目录下新建独立脚本,路径可设为
apps/[你的应用名]/scripts/generate-swagger.ts,独立封装Swagger生成逻辑,直接导入项目根模块即可,不需要复用main.ts里的bootstrap逻辑:
import { NestFactory } from '@nestjs/core'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import { writeFileSync } from 'fs'; import path from 'path'; import { AppModule } from '../src/app.module'; async function generateSwagger() { // 仅创建实例,不绑定端口不启动服务 const app = await NestFactory.create(AppModule, { logger: false }); const options = new DocumentBuilder() .setTitle('Cats example') .setDescription('The cats API description') .setVersion('1.0') .addTag('cats') .build(); const document = SwaggerModule.createDocument(app, options); const outputPath = path.resolve(process.cwd(), 'dist/apps/[你的应用名]/swagger.json'); writeFileSync(outputPath, JSON.stringify(document), { encoding: 'utf8' }); await app.close(); } generateSwagger();
- 然后修改应用的
project.json配置,新增独立的swagger生成目标,并把它设为build的前置依赖,NX构建时会自动先执行生成逻辑:
{ "targets": { "build": { "executor": "@nx/webpack:webpack", "dependsOn": ["generate-swagger"], // 原有build配置保持不变即可 }, "generate-swagger": { "executor": "nx:run-commands", "options": { "command": "tsx apps/[你的应用名]/scripts/generate-swagger.ts", "cwd": "{workspaceRoot}" } } } }
这个方案没有侵入性,跨项目的依赖导入会被NX自动解析,不会出现模块找不到的问题。
方案2:构建后基于产物运行
如果必须基于构建后的产物执行生成逻辑,需要调整webpack打包配置,把Swagger生成脚本作为独立入口打包,避免单文件bundle的私有作用域导致内部模块无法被外部引用:
- 同样先写好独立的Swagger生成TS脚本
- 修改应用根目录下的
webpack.config.js,把生成脚本加入打包入口,构建后会在dist目录下额外输出独立的swagger-gen.js文件,所有依赖已经被打包进文件内:
const path = require('path'); module.exports = (config, context) => { // 保留原有单文件打包配置 const originalEntry = config.entry; config.entry = { main: originalEntry, 'swagger-gen': path.resolve(context.root, 'apps/[你的应用名]/scripts/generate-swagger.ts') }; config.output.filename = '[name].js'; return config; };
- 在project.json里新增build后置执行命令,构建完成后直接运行生成的bundle即可输出swagger.json:
{ "targets": { "build": { // 原有配置不变 "dependsOn": [], "outputs": ["{options.outputPath}"] }, "generate-swagger-build": { "executor": "nx:run-commands", "options": { "command": "node dist/apps/[你的应用名]/swagger-gen.js" }, "dependsOn": ["build"] } } }
不要尝试直接从构建输出的单文件main.js里导入app实例,NX默认的webpack打包会把所有模块封装到立即执行函数的私有作用域内,不会对外暴露任何内部变量,直接导入拿不到有效引用。
内容的提问来源于stack exchange,提问作者JDev
相关产品推荐
相关产品推荐

