OpenAPI 文档
VextJS 内置 OpenAPI 文档自动生成功能。基于路由的 validate 和 docs 配置,框架自动生成 OpenAPI 3.0 规范的 JSON 文档,并提供 Scalar API Reference 在线查看和交互式调试。
快速开始
1. 启用 OpenAPI
在配置中开启 openapi.enabled:
2. 在路由中添加文档信息
3. 访问文档
启动项目后,访问以下地址:
文档配置
全局配置
在 config/default.ts 中配置 OpenAPI 全局信息:
路由级文档配置
每个路由可以通过 options.docs 配置其 OpenAPI 文档信息:
docs 配置详解
summary — 接口摘要
一句话描述接口功能,显示在文档 UI 的接口列表中:
description — 详细描述
支持 Markdown 格式的详细说明,展开接口时显示:
tags — 标签分组
控制接口在文档中的分组。如果不指定,框架会从路由文件路径自动推断:
operationId — 操作标识
全局唯一的操作标识符。如果不指定,框架自动推断:
hidden — 隐藏路由
不希望出现在文档中的路由(如内部接口):
deprecated — 标记废弃
标记接口为已废弃,在文档中会有删除线和废弃提示:
security — 安全方案
默认情况下,框架会从路由的 middlewares 自动推断安全方案。通过 guardSecurityMap 配置中间件名到安全方案的映射:
路由使用 middlewares: ['auth'] 时,OpenAPI 文档自动标注需要 Bearer Token 认证。
手动覆盖:
responses — 响应定义
自定义路由的响应文档。key 为 HTTP 状态码:
响应 schema 使用与 validate 相同的 DSL 语法,自动转换为 JSON Schema。
响应示例
多响应示例
自定义 Content-Type
响应头
validate 与文档的自动联动
路由中的 validate 规则会自动映射到 OpenAPI 文档,无需重复编写:
自动生成的 OpenAPI 参数:
validate.body 的规则自动映射为 requestBody(JSON schema):
生成的 requestBody schema:
按环境控制
建议在开发环境启用文档,生产环境关闭:
如果生产环境需要保留 API 文档(只读参考):
自定义文档路径
导入外部 OpenAPI
Scalar 支持同时加载多个 OpenAPI 文档,在文档页面顶部显示切换器。通过 scalar.sources 配置:
每个 source 支持以下字段:
当配置了 sources 时,框架自动生成的 /openapi.json 会作为第一个 source 注入(除非 sources 中已包含相同路径),无需手动重复声明。
也可以通过 content 内联提供规范(适合小型/固定的 spec):
自定义 CDN / 本地资产
默认情况下,Scalar 通过 jsDelivr CDN 加载 JS 文件。如果需要在内网、离线环境或需要版本锁定的场景下使用,可以通过 scalar.cdnUrl 自定义加载地址:
对于完全离线的环境,你需要:
- 从 npm 下载
@scalar/api-reference包 - 将 JS 文件托管到内网静态服务器或应用的 public 目录
- 将
cdnUrl指向该地址 :::
与第三方工具集成
导出 OpenAPI 规范
访问 http://localhost:3000/openapi.json 获取完整的 OpenAPI 3.0 JSON 文件,可用于:
- Postman — 导入 API 集合
- Insomnia — 导入 API 工作区
- 代码生成 — 使用
openapi-generator生成客户端 SDK - API 网关 — 导入到 Kong、AWS API Gateway 等
- 文档平台 — 导入到 Stoplight、ReadMe 等
示例:生成 TypeScript 客户端
文档最佳实践
1. 始终提供 summary
summary 是接口在文档列表中最重要的标识,应简洁明了:
2. 使用一致的标签
统一使用中文或英文标签,并在全局 tags 中预定义顺序和描述:
3. 为错误响应添加文档
常见的错误码应在 responses 中说明:
4. 隐藏内部接口
框架内部或运维使用的接口应标记为 hidden:
5. 善用 deprecated
API 版本迭代时,使用 deprecated 而非直接删除旧接口:
多级目录示例
VextJS 的文件路由支持多层嵌套目录,每一级目录自动映射为 URL 路径段。配合 tags 分组,多级路由在 Scalar 文档页面中自动归类展示。
目录结构
路径映射对照
全局 tags 定义
在配置中预定义标签,Scalar 文档会按标签分组展示:
各路由文件
routes/api/v1/users.ts — 用户公开接口
routes/api/v1/users/[id]/orders.ts — 用户订单(多级动态参数)
routes/api/v1/admin/dashboard.ts — 管理后台
routes/api/v1/admin/users.ts — 管理后台用户管理
routes/webhooks/stripe.ts — 第三方回调
生成的 OpenAPI 路径
以上目录结构最终自动生成以下 OpenAPI 路径,在 Scalar 文档中按 tags 分组展示:
:::tip 多级目录最佳实践
- 用目录层级表达 URL 结构:
api/v1/admin/自动映射为/api/v1/admin/前缀,无需手动拼接 - 动态参数用
[param]目录:users/[id]/orders.ts自动变为/users/:id/orders,文件内的param校验会出现在 OpenAPI 文档中 - tags 统一管理:在全局配置中预定义 tags,各路由文件通过
docs.tags引用,Scalar 文档按标签分组 - 文件名即路由:无需
app.group()或手动注册路由前缀,目录结构就是路由结构 :::
标签分组(x-tagGroups)
OpenAPI 3.x 规范的 tags 是一维扁平列表,不原生支持嵌套层级。当路由数量较多时,所有 tags 在 Scalar 文档侧边栏中平铺并列,不便于导航。
VextJS 通过 Scalar 支持的 x-tagGroups 扩展 实现两级导航:将多个 tags 归入更高级别的分组(group),在 Scalar 侧边栏中展示为可折叠的分组层级。
自动推断(默认行为)
当路由文件分布在多个顶层目录时,框架自动推断 x-tagGroups:
- 提取每条路由文件在
routes/之后的第一层目录名作为分组名(首字母大写) - 直接位于
routes/下的文件归入 "General" 分组 - 如果所有路由都在同一个分组中,则不生成
x-tagGroups(避免冗余)
生成的 x-tagGroups:
:::tip 分组按字母排序,General 始终排在最后。同一分组内的 tags 也按字母排序且自动去重。
手动配置(覆盖自动推断)
如果自动推断的分组不满足需求,可以在配置中显式指定 tagGroups:
配置了 tagGroups 后,框架不再自动推断,直接使用用户配置。请确保所有 tags 都被覆盖到至少一个分组中,否则未分组的 tags 在 Scalar 中可能不显示。
效果对比
与热重载的兼容性
在 dev 模式下,热重载(soft reload)会自动重新生成 x-tagGroups:
- 路由文件变更 → 触发热重载
- 创建新的 adapter 实例
- 重新加载路由 + 收集路由元信息
- 重新生成 OpenAPI spec(含
x-tagGroups) - 在新 adapter 上重新注册
/docs和/openapi.json端点
无需重启 dev server,刷新文档页面即可看到更新后的分组。
完整示例
下一步
- 了解 参数校验 的 DSL 语法如何映射到 OpenAPI
- 学习 配置 中 OpenAPI 的完整选项
- 查看 Adapter 架构 了解不同 Adapter 下的文档行为
- 探索 测试 如何验证 API 文档的准确性