在 Wasp 项目中集成 Swagger UI:为你的 React + Node.js API 自动生成可交互接口文档

发布时间:2026/9/14 14:16:08
在 Wasp 项目中集成 Swagger UI:为你的 React + Node.js API 自动生成可交互接口文档 在 Wasp 项目中集成 Swagger UI为你的 React Node.js API 自动生成可交互接口文档【免费下载链接】waspThe batteries-included full-stack framework for the AI era. Develop JS/TS web apps (React, Node.js, and Prisma) using declarative code that abstracts away complex full-stack features like auth, background jobs, RPC, email sending, end-to-end type safety, single-command deployment, and more.项目地址: https://gitcode.com/GitHub_Trending/wa/wasp本指南以 Wasp 开源仓库中的官方集成文档 web/docs/guides/integrations/swagger-ui.md 为主体结合仓库内代码生成器的真实实现完整演示如何在 Wasp 应用中接入 Swagger UI通过swagger-jsdoc扫描 JSDoc 注解预生成 OpenAPI 规范、借助swagger-ui-express在/api-docs提供可交互的接口文档页并支持 JWT Bearer 认证、POST 请求体、路径/查询参数标注与 UI 自定义。读完本文你将掌握一套可复制、可运行的 API 文档化方案并理解 Wasp 中间件系统MiddlewareConfigFn在背后的工作方式。Wasp 是一个开箱即用的全栈框架用声明式的main.wasp.ts描述应用底层自动生成 React前端、Node.js Express后端与 Prisma数据层代码。当你通过api(GET, /status, getStatus)这样的声明暴露自定义 API 时Wasp 会替你生成对应的 Express 路由。当 API 数量变多一套能浏览、测试端点的接口文档就显得必不可少——Swagger UI 正是为此而生。一、先理解 Wasp 的 API 与中间件机制源码级铺垫在动手之前先看两条与本文强相关的底层机制这能帮你理解后面每个配置文件的用意。1. API 命名空间apiNamespace如何变成 Express 路由在 Wasp 的代码生成模板 waspc/data/Generator/templates/server/src/routes/apis/index.ts 中每一个apiNamespace(/path, { middlewareConfigFn })声明都会被生成为router.use(/api-docs, globalMiddlewareConfigForExpress(swaggerMiddleware))也就是说命名空间本质上是一条挂载在 Express Router 上的中间件链所有以该前缀开头的请求都会先经过你提供的middlewareConfigFn处理——这正是我们把 Swagger UI 中间件挂到/api-docs下的原理。2. 中间件配置函数MiddlewareConfigFn的本质Wasp 的中间件是一个Mapstring, RequestHandler见 waspc/data/Generator/templates/sdk/wasp/server/middleware/globalMiddleware.ts而MiddlewareConfigFn的类型定义为export type MiddlewareConfigFn (middlewareConfig: MiddlewareConfig) MiddlewareConfig服务端默认注入了一组全局中间件见 waspc/data/Generator/templates/server/src/middleware/globalMiddleware.tsconst defaultGlobalMiddlewareConfig: MiddlewareConfig new Map([ [helmet, helmet()], [cors, cors({ origin: config.allowedCORSOrigins })], [logger, logger(dev)], [express.json, express.json()], [express.urlencoded, express.urlencoded()], [cookieParser, cookieParser()] ])当你的middlewareConfigFn被调用时Wasp 会先克隆全局 Map 再交给你的函数修改globalMiddlewareConfigForExpress的实现是new Map(globalMiddlewareConfig)后应用你的函数因此你对某个命名空间中间件的增删改不会污染其他路由。理解了这一点下文middlewareConfig.delete(helmet)与middlewareConfig.set(swaggerServe0, ...)的含义就一目了然了。二、开始集成六步搭建 Swagger UI1. 安装依赖npm install swagger-jsdoc swagger-ui-express npm install --save-dev types/swagger-jsdoc types/swagger-ui-expressswagger-jsdoc负责读取源码中的 JSDoc 注解将其与 OpenAPI 定义合并生成一份 OpenAPI 3.0 规范swagger 规范。swagger-ui-express把规范渲染成语义化、可交互的 Web 页面。两个types包为 TypeScript 项目提供类型提示Wasp 默认开启 TypeScript类型安全是框架的核心特性之一。2. 在 main.wasp.ts 中配置 API 命名空间在main.wasp.tsWasp 应用的声明式配置入口等价于 Wasp 0.2x 时代的.wasp文件中添加一个 API 命名空间并指向我们要写的 Swagger 中间件import { api, apiNamespace, app } from wasp.sh/spec import { getStatus } from ./src/apis with { type: ref } import { swaggerMiddleware } from ./src/swagger-ui with { type: ref } export default app({ name: MyApp, wasp: { version: ^0.24.0 }, title: my-app, head: [link relicon href/favicon.ico /], spec: [ apiNamespace(/api-docs, { middlewareConfigFn: swaggerMiddleware }), api(GET, /status, getStatus, { auth: false }), ], })关键点apiNamespace(/api-docs, ...)表示挂载在/api-docs前缀下的所有请求都会先经过swaggerMiddleware。api(GET, /status, getStatus, { auth: false })声明一个公开的、不需要登录的GET /status接口。根据 apis/index.ts 模板{ auth: false }的路由不会注入auth中间件请求处理函数收到的req也就不会带有user字段。3. 创建预生成 Swagger 规范的脚本Wasp 应用编译后服务端运行在打包产物Docker 镜像中生产环境的镜像里并不包含src/源码目录而swagger-jsdoc恰恰需要在运行时扫描源码文件。因此不能在运行时动态生成规范必须先把它预生成成一个 TypeScript 模块随服务端一起打包。创建scripts/generate-swagger.jsimport swaggerJsdoc from swagger-jsdoc; import { writeFileSync } from fs; const spec swaggerJsdoc({ definition: { openapi: 3.0.0, info: { title: My API, version: 1.0.0, description: API documentation for my Wasp application, contact: { name: API Support, url: https://example.com, email: supportexample.com, }, }, components: { securitySchemes: { bearerAuth: { type: http, scheme: bearer, bearerFormat: JWT, description: Enter your JWT token in the format: Bearer {token}, }, }, }, security: [{ bearerAuth: [] }], }, apis: [./src/**/*.ts, !./src/swaggerSpec.ts], }); writeFileSync( ./src/swaggerSpec.ts, const swaggerSpec ${JSON.stringify(spec, null, 2)} as const;\nexport default swaggerSpec;\n, ); console.log(swaggerSpec.ts generated);说明definition中是 OpenAPI 3.0 的基础元信息接口标题、版本、描述、联系方式。components.securitySchemes.bearerAuth声明了一个 HTTP BearerJWT认证方案security: [{ bearerAuth: [] }]使其成为全局默认安全要求若某个接口不需要认证可在该接口的 JSDoc 中写security: []覆盖。apis配置了swagger-jsdoc的扫描范围扫描./src/**/*.ts但排除生成的./src/swaggerSpec.ts自身。脚本把生成结果以as const的形式写入src/swaggerSpec.ts以获得精确的字面量类型推断。每当新增或修改 JSDoc 注解后重新运行node scripts/generate-swagger.js这会重新生成src/swaggerSpec.ts并被服务端打包开发与生产环境都能正常工作。:::notesrc/swaggerSpec.ts是生成产物建议把它加入.gitignore避免每次运行脚本都产生无意义的 diff。 :::4. 创建 Swagger 中间件在src/swagger-ui.ts中编写中间件把预生成的规范交给swagger-ui-express渲染并动态注入服务端地址import * as express from express; import helmet from helmet; import swaggerUi from swagger-ui-express; import { env, MiddlewareConfigFn } from wasp/server; import baseSwaggerDoc from ./swaggerSpec; const swaggerDoc { ...baseSwaggerDoc, servers: [{ url: env.WASP_SERVER_URL, description: API server }], }; export const swaggerMiddleware: MiddlewareConfigFn (middlewareConfig) { middlewareConfig.delete(helmet); middlewareConfig.set( helmet, helmet({ contentSecurityPolicy: false, hsts: false, }), ); swaggerUi.serve.forEach((handler, i) { middlewareConfig.set(swaggerServe${i}, handler); }); middlewareConfig.set( swaggerSetup, ( req: express.Request, res: express.Response, next: express.NextFunction, ) { return swaggerUi.setup(swaggerDoc, { explorer: true, customCss: .swagger-ui .topbar { display: none }, swaggerOptions: { persistAuthorization: true, url: /api-docs/swagger.json, }, })(req, res, next); }, ); return middlewareConfig; };逐段拆解servers动态注入env.WASP_SERVER_URL是 Wasp 注入的服务端环境变量用于指明尝试请求的服务地址避免硬编码 localhost 或生产域名。这里展开baseSwaggerDoc后覆盖servers字段。middlewareConfig.delete(helmet)再setSwagger UI 页面依赖内联脚本与内联样式默认的helmet会通过Content-Security-Policy阻止它们因此这里用contentSecurityPolicy: false重新启用同时关闭hsts以避免本地测试时被强制 HTTPS。这正是前面提到的克隆后修改互不影响机制的实战体现。swaggerUi.serve逐个注册swagger-ui-express的serve是一个 Express 中间件数组包含静态资源、swagger.json路由等这里按索引展开注册为swaggerServe0、swaggerServe1……swaggerSetupswaggerUi.setup(swaggerDoc, options)生成渲染处理器。选项含义explorer: true显示右上角的Explore搜索框方便切换 API 文档源customCss自定义样式这里隐藏了 Swagger UI 顶栏的 logo/搜索条swaggerOptions.persistAuthorization: true在浏览器 localStorage 中记住已填写的 Authorization 令牌刷新页面后不用重新输入swaggerOptions.url指向/api-docs/swagger.json即由swaggerUi.serve提供的规范 JSON 端点Try it out 时会请求该 URL 对应的服务端servers[0].url。5. 用 JSDoc 注解你的 API在 API 定义文件如src/apis.ts上方添加带swagger标记的 JSDoc 注释swagger-jsdoc会自动解析它们合并进规范import { GetStatus } from wasp/server/api; /** * swagger * /status: * get: * summary: Get API status * description: Returns the current status of the API * tags: * - Status * security: * - bearerAuth: [] * responses: * 200: * description: Successful response * content: * application/json: * schema: * type: object * properties: * message: * type: string * 401: * description: Unauthorized * 500: * description: Server error */ export const getStatus: GetStatus async (req, res) { return res.json({ message: OK }); };要点import { GetStatus } from wasp/server/api是 Wasp 为自定义 API 导出的请求/响应类型保证处理器签名与生成的 Express 路由类型安全。JSDoc 中的路径/status与main.wasp.ts中api(GET, /status, ...)声明的路径保持一致Swagger 才能正确对应到真实端点。summary、description、tags会直接呈现在文档 UI 上responses描述各个状态码的返回结构。每个接口都可以单独声明security由于第 3 步全局声明了bearerAuth这里显式写- bearerAuth: []可保持一致性若某个接口公开可写security: []。6. 启动并访问文档启动你的 Wasp 应用wasp start然后在浏览器中打开http://localhost:3001/api-docs即可看到包含全部已标注端点的交互式 API 文档页支持Authorize填入 JWT、展开端点后Try it out直接发送真实请求。三、标注不同类型的请求除了上述GET示例Swagger JSDoc 语法同样覆盖常见的 POST 请求体、路径参数与查询参数。POST 请求与请求体requestBody/** * swagger * /users: * post: * summary: Create a new user * tags: * - Users * requestBody: * required: true * content: * application/json: * schema: * type: object * required: * - email * - password * properties: * email: * type: string * format: email * password: * type: string * minLength: 8 * responses: * 201: * description: User created successfully * 400: * description: Invalid input */requestBody.required: true标记请求体必填content定义 JSON 媒体的 schema。properties中format: email表示邮箱格式minLength: 8约束密码最短长度——Swagger UI 的 Try it out 会根据这些约束生成示例值并进行基础校验。路径参数Path Parameters/** * swagger * /users/{id}: * get: * summary: Get user by ID * tags: * - Users * parameters: * - in: path * name: id * required: true * schema: * type: string * description: User ID * responses: * 200: * description: User found * 404: * description: User not found */in: path表示参数位于 URL 路径中/users/{id}required: true是路径参数的必要条件name必须与路径中的占位符一致。查询参数Query Parameters/** * swagger * /users: * get: * summary: List users * tags: * - Users * parameters: * - in: query * name: page * schema: * type: integer * default: 1 * description: Page number * - in: query * name: limit * schema: * type: integer * default: 10 * description: Items per page * responses: * 200: * description: List of users */in: query表示参数附加在 URL 查询串?page1limit10上schema.default会作为默认值预填到 Try it out 的请求中。四、进一步自定义自定义样式与站点标题swaggerUi.setup的选项支持外观与品牌定制swaggerUi.setup(swaggerDoc, { customCss: .swagger-ui .topbar { display: none } .swagger-ui .info { margin: 20px 0 } , customSiteTitle: My API Documentation, customfavIcon: /favicon.ico, });customCss直接注入 CSS可隐藏顶栏、调整.info区域间距等customSiteTitle设置浏览器标签页标题customfavIcon设置页面 favicon 路径这里指向 Wasp 的public/favicon.ico。用 Tags 给接口分组当接口增多时可以用tags在scripts/generate-swagger.js的definition中预定义分组对应各端点 JSDoc 里引用的tagsSwagger UI 会按标签分组展示const spec swaggerJsdoc({ definition: { // ... other config tags: [ { name: Users, description: User management endpoints }, { name: Posts, description: Blog post endpoints }, { name: Auth, description: Authentication endpoints }, ], }, apis: [./src/**/*.ts, !./src/swaggerSpec.ts], });这样每个接口注解中的tags: - Users就会归入 Users 分组文档页面的可读性大幅提升。五、最佳实践小结保持路径一致main.wasp.ts中api()的路径/方法与 JSDoc 注解中的路径/方法必须一一对应否则文档中会出现幽灵端点。生成产物入库策略src/swaggerSpec.ts建议加入.gitignore并在 CI 或prebuild钩子中运行node scripts/generate-swagger.js保证每次构建都有最新规范。安全边界/api-docs挂载了 Swagger UI 的静态资源与规范 JSON生产环境如需保护可以在main.wasp.ts中给命名空间配置对应的认证中间件或部署时在网关卡控。中间件隔离得益于 Wasp 的globalMiddlewareConfigForExpress克隆机制对/api-docs中间件的任何修改都不会影响其他 API 路由——你完全可以放心地只为文档页关闭 CSP。至此你的 Wasp 应用拥有了与代码同源的、可交互的 Swagger UI 接口文档开发、联调、对外交付都更加高效。【免费下载链接】waspThe batteries-included full-stack framework for the AI era. Develop JS/TS web apps (React, Node.js, and Prisma) using declarative code that abstracts away complex full-stack features like auth, background jobs, RPC, email sending, end-to-end type safety, single-command deployment, and more.项目地址: https://gitcode.com/GitHub_Trending/wa/wasp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询