像Swagger UI、Slate或Spectacle这样的项目提供了强大的文档功能,但它们都专注于展示单个API——如果我们想通过一个门户清晰地提供多个API的文档呢?
随着支持公共API的团队数量不断增加,或需要向其他团队提供“内部目录”的团队,拥有一个地方让用户了解各种API如何协同工作至关重要。精心设计和维护的文档有助于提高采用率,在使用服务时强制执行最佳实践,并且是展示新功能上线的好方法。
在本系列文章中,我们将探讨如何通过使用React.js动态地将OAS定义传递到Swagger UI中来创建解决方案(第1部分),自定义这个基本门户(第2部分),最后部署到外部主机(第3部分)。本系列后续部分将侧重于更小的功能点 — 例如使用“演练”风格页面增强文档,或连接到私有托管定义。 SwaggerHub 将作为我们的API规范托管平台,尽管本系列后续将探讨加载它们的替代方案。
这些步骤适用于对React和OpenAPI有一定了解的人,但对于初次接触这些工具的人来说也应该足够简单。
最终门户的模板版本可在此处 找到,可用于启动本项目;运行示例可在此处.托管。
什么是OpenAPI、Swagger UI或SwaggerHub?
OpenAPI规范(OAS)是一个REST定义标准,由OpenAPI倡议 — Linux基金会的一部分 — 维护。该规范最近发布了3.0版本,并在整个行业中得到了持续的采用和支持。像OAS这样的标准有助于促进“设计优先”或“定义驱动”的开发策略,让利益相关者在深入编写代码之前规划API及其功能。由于存在一个所有人都可遵循的计划,即将到来的变更和测试要求可以提前传达。
Swagger UI是Swagger工具集的一部分,该工具集是一系列支持OAS的开源项目。它长期以来与定义并行使用,作为一种通过最少设置快速提供交互式文档的方式。我们将在我们的单页应用程序中利用Swagger UI提供的节点包。
SwaggerHub 是由SmartBear从零开始构建的平台解决方案,旨在大规模支持OAS。它非常适合由单个组织或团队管理多个不同API的想法,我们可以利用其后端将这些API按需加载到我们的文档门户中。通过使用SwaggerHub这样的工具,我们可以更新和定义要向API消费者展示的“当前”规范,同时支持持续的设计和开发。
环境设置
既然我们了解了将要使用的工具, 那么让我们确保我们拥有构建项目所需的依赖项。本系列稍后我们将探讨如何将其部署到外部主机,或在容器内运行 — 但现在,让我们先在本地运行它。这里的目标是尽可能少地进行配置,以保持我们的部署选项开放,因此我们只有一个初始要求:NodeJS。
通过运行node -v
验证您是否安装了晚于5.2.0的node版本,因为我们将使用npx来构建我们的初始起点。
我们不会搭建一个完整的React开发环境,而是使用create-react-app项目作为起点。这使我们可以在一个命令中获得所有依赖项和基本结构。
首先,导航到将存放您项目的父文件夹,然后运行npx create-react-app oas-doc-portal
NPX将负责构建基础项目,您可以通过进入新项目文件夹并启动默认应用程序来验证一切是否顺利。
$ cd oas-doc-portal
$ npm start

如果一切在浏览器中渲染正确,我们就可以继续将其连接到我们的定义存储库了。
这也是将项目连接到您选择的GIT仓库系统并进行首次推送的好时机。
渲染单个规范
在进行诸如动态传递定义之类的冒险操作之前,让我们确保我们可以从远程资源加载并渲染单个定义。这将为我们提供一个可靠的起点,并使我们在不可避免地出错时能够轻松识别。本教程将使用此处提供的Swagger Petstore定义:https://petstore.swagger.io/v2/swagger.json
这一切都通过swagger-ui node包实现,因此让我们使用ctrl+c
停止应用程序并将其添加到我们的应用程序中。
- 运行
npm install swagger-ui
将swagger-ui安装到项目中
- 打开
/src/App.js
- 在页面顶部的导入语句下方添加swagger-ui。
为了避免稍后重新配置 ,我们可以将构造函数添加到应用程序中,并为OAS链接创建一个状态。我们将根据新的OAS链接动态更新此值,因此这是一个保存引用的绝佳位置。这篇文章更深入地探讨了React如何处理状态。
我们通过向swagger-ui传递一个定义链接来渲染文档。由于该链接将很快动态更新,我们应该利用React生命周期来保持一切最新 — 在这种情况下 componentDidMount
将完成这项工作(我们稍后会根据需求变化进行调整)。
Swagger UI组件支持多种不同的参数,具体取决于我们希望它如何渲染,但对于我们最初的用例:
- 我们指示它在我们接下来将创建的
api-data
元素内部渲染文档。
- 状态对象中存储的URL引用,告诉它从何处加载定义。
请删除create-react-app为我们生成的占位符渲染元素,并将其替换为我们新定义的div要求
现在,Swagger UI将查找页面上的api-data
元素,并在其中渲染我们的文档。如果我们启动应用程序并重新加载浏览器,应该会看到之前的占位符页面现在已经显示了Swagger Petstore的基本表示!

它并不美观,但数据就在那里 — 我们现在可以手动更新definitionLink
值以渲染新的API数据。本质上,接下来的步骤将是作为应用程序本身的一部分来完成这项工作。
此时应用程序应如下所示:
动态更新定义
我们门户的最终目标是显示API列表,用户可以在每个API之间点击并查看主窗口中的文档更新。为此,我们将在侧边栏中显示列表,并随着用户点击列表来更新definitionLink
值。
第一步,我们需要考虑从哪里获取API列表。为了本教程的目的,我们将使用SwaggerHub作为我们的仓库系统来提供各种API定义。如果您还没有SwaggerHub账户,可以在此处免费注册,创建一个组织并添加一些定义。或者,您也可以使用本教程中提供的示例组织。
现在我们有了一个SwaggerHub组织和一些托管在那里的定义,我们可以开始考虑将它们拉取到我们的门户中。这将全部由SwaggerHub API驱动,因此作为一个起点,我们将编写一个新函数来处理我们不同的API调用,并避免重复编写大量代码。
- 向我们的应用程序添加一个新的
swaggerhub
函数
此函数将允许我们在几个不同级别对SwaggerHub进行调用,并且应该足够灵活,以支持我们后续构建的新功能。接下来,我们希望查看如何获取API“列表”。
SwaggerHub API允许对组织进行请求,其响应包含API名称及其位置链接的数组,这将非常适合我们的用例。
让我们使用swaggerhub
函数并创建一个新的getOrganizationData
调用。这将接收一个输入参数,即我们组织的名称,并将SwaggerHub的响应设置为状态级别的API列表。
现在更新状态对象以期待definitionList
。这也是添加另一个稍后将使用的键/值对的好时机,并且我们应该将这两个新函数绑定到应用程序。
我们还在getOrganizationData
调用中引用了一个组织,但尚未将该信息存储在任何地方。稍后我们还会想添加一个副标题和公司徽标,因此让我们创建一个配置文件来存储这些信息。
- 在
/src
目录下,创建一个名为organization_config.json
的新文件
- 将以下对象添加到配置文件中,并用您的组织信息填充它
- 最后创建一个
componentWillMount
函数来处理页面加载时的数据映射
我们已经构建了处理获取API列表的模块 — 现在是时候开始考虑如何将这些信息渲染给我们的消费者了。接下来的几个步骤将构建一个新的组件Sidebar
,以及一个新的元素调用apiLink
,它将被填充到侧边栏中。
- 在
/src
中创建一个新文件 — Sidebar.js
。侧边栏的开始会非常简单,只是一个基本结构和一些我们存储在配置文件中的显示名称数据
- 在主应用程序的
render
部分,更新以包含新组件 — Sidebar
。此时我们还需要向下传递它所需的数据和函数
- 确保也将
Sidebar
导入到应用程序中。我们还应该从swagger-ui模块中引入CSS文件,以稍微美化我们的文档视图。我们稍后将探讨如何自定义此项。
- 为了在浏览器中稍微整理一下,让我们添加一些快速CSS,以明确我们接下来将要进行的更改。在
App.css
文件中,我们可以开始组织我们的页面

太好了!我们已经为侧边栏建立了一个基本结构(一个标题和一个将包含链接的主体) — 但我们缺少一个关键部分,即链接本身。我们已经通过传入的props
传递了大部分所需数据,所以现在只需编写一些逻辑来处理并更新我们的状态对象。
- 创建一个新文件
/src/APILink.js
并用它来处理通过侧边栏传入的数据
- 这里我们有一些请求,但它们尚未向下传递。首先,让我们在App.js中创建
updateDefintionLink
函数,在构造函数中绑定它,并将其传递给Sidebar
- 现在我们需要连接两者,所以让我们更新
Sidebar.js
以包含以下内容
添加了什么?
- 首先,我们正在验证组织数据是否已加载,如果尚未加载,则使用
getOrganizationData
发出请求。
- 一旦我们有了API数据,我们就遍历它并将其馈送到新的元素
APILink
中,该元素将根据用户的选择处理更新我们的definitionLink
组件。我们检查它是否在SwaggerHub中“发布”,然后将链接推送到apiLinks
数组。
- 最后,我们从
APILink.js
中导入了一个新的内容。
完美。现在如果我们重新加载页面,应该会看到我们的侧边栏已经填充了所有不同API的名称!让我们快速更新CSS来整理它们
现在我们应该能看到所有链接显示在左侧,并且可以点击。只有一个问题 — 文档组件实际上没有更新! 幸运的是,这是一个快速修复。目前,我们的updateDefinitionLink
正在正常工作(如果我们使用console.log
,可以看到URL正在正确传递)— Swagger UI只是不知道它已更新,因为它处于我们所设定的生命周期阶段。
要解决此问题,只需将我们之前的componentDidMount
函数更新为App.js
中的componentDidUpdate
,当我们重新加载页面时,它应该会随着每个新链接的选择而更新!

总结
至此,我们有了一个功能齐全(尽管非常基础)的API文档门户!我们可以继续添加新的API版本或定义,在后端更改发布和取消发布状态 — 我们的文档将始终保持最新。
本系列下一部分将探讨如何有效地开始为侧边栏和Swagger UI元素设置样式,以个性化文档,最后一部分将部署到几个不同的托管站点。
下面是目前我们应该拥有的最终代码。
感谢您的阅读!正在寻找更多API资源?订阅Swagger新闻通讯。每月接收包含我们最佳API文章、培训、教程等的电子邮件。 订阅