TypeScript项目中swagger-ui-express与swagger-jsdoc编译后失效问题
问题解决方法
核心原因
用esbuild编译后,dist目录下只有编译好的JS文件,没有原TS文件。你当前的apis配置['**/routes/**/*.ts', '**/routes/**/*.js']在运行node dist/index.js时,要么找不到TS文件(不在dist目录内),要么路径匹配不到正确的JS文件,导致swagger-jsdoc无法生成有效的OpenAPI spec,最终Swagger页面加载失败。而tsx是直接运行TS源码,所以能正常找到文件。
具体解决方案
方案1:修改apis路径指向编译后的JS文件
调整swagger-jsdoc的配置,让它指向dist目录下的JS文件:
const swaggerSpec = swaggerJsDoc({ definition: { openapi: '3.0.0', info: { title: 'API Docs', version: '1.0.0' }, }, apis: ['./dist/routes/**/*.js'], // 指向编译后的文件 });
如果运行时工作目录不是项目根目录,推荐用绝对路径避免问题:
import path from 'path'; const swaggerSpec = swaggerJsDoc({ definition: { openapi: '3.0.0', info: { title: 'API Docs', version: '1.0.0' }, }, apis: [path.resolve(__dirname, './routes/**/*.js')], // __dirname对应dist目录,直接匹配子目录下的JS文件 });
方案2:提前生成Swagger Spec(推荐)
这种方式彻底避免运行时动态读取文件的路径问题,步骤如下:
- 新建生成脚本
src/generate-swagger.ts:
import swaggerJsDoc from 'swagger-jsdoc'; import fs from 'fs'; import path from 'path'; const options = { definition: { openapi: '3.0.0', info: { title: 'API Docs', version: '1.0.0' }, }, apis: ['./src/routes/**/*.ts'], // 直接读取源码TS文件 }; const swaggerSpec = swaggerJsDoc(options); // 将生成的spec写入dist目录 fs.writeFileSync(path.resolve(__dirname, '../dist/swagger-spec.json'), JSON.stringify(swaggerSpec));
- 修改package.json的编译脚本,先生成spec再编译:
{ "scripts": { "build": "rimraf dist && tsx src/generate-swagger.ts && esbuild ./src/index.ts --target=es2016 --bundle --platform=node --outdir=dist", "start": "node dist/index.js" } }
- 在
src/index.ts里导入生成的spec并使用:
import swaggerUi from 'swagger-ui-express'; import swaggerSpec from '../dist/swagger-spec.json'; // ... 其他代码逻辑 app.use('/docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec));
额外注意点
如果你的TS配置里用了路径映射(比如paths字段),swagger-jsdoc直接读取TS文件时可能无法解析别名路径,此时提前生成spec的方式更可靠——tsx运行生成脚本时会处理TS的路径映射,确保能正确找到文件。
内容的提问来源于stack exchange,提问作者João Casarin
相关产品推荐
相关产品推荐

