使用 Docusaurus、GitLab CI 和 TypeDoc 构建跨微服务的集中式文档
Source: Dev.to
在现代微服务架构中,文档经常分散在数十个仓库中。每个服务都有自己的文档,开发者很难找到信息,新的团队成员入职就像一次寻宝。最近我通过构建一个 集中式文档系统 来解决了这个问题,该系统自动聚合 TypeDoc‑生成的 API 文档 与自定义用户指南,形成一个可搜索的 Docusaurus 站点。
分散文档的问题
我们的微服务生态系统是逐步自然增长的。每个仓库都有自己的技术文档,但访问它们需要:
- 知道要查看哪个仓库
- 将其克隆到本地
- 在
README文件中导航
对于新开发者来说,这令人不堪重负。对于 AI‑训练而言,几乎不可能为系统提供我们架构的完整视图。
我们需要一个解决方案,使得:
- 自动生成并集中来自 TypeScript 代码库的 API 文档
- 将自定义用户文档与代码‑级文档一起包含
- 维护开销最小
- 随代码变更自动更新
- 为所有文档提供单一访问入口
架构
该解决方案利用三项关键技术协同工作:
| 技术 | 角色 |
|---|---|
| TypeDoc | 从 TypeScript 源代码(接口、类、方法、内联注释)生成全面的 API 文档。每个微服务仓库都会创建自己的文档快照。 |
| GitLab CI | 通过计划的流水线处理整个过程。与其将生成的文档提交到每个服务仓库(这会导致仓库膨胀并产生噪音),CI 流水线会将文档推送到集中位置。 |
| Docusaurus | 作为展示层,构建快速的静态文档站点,将所有服务的内容聚合到统一、可搜索的界面中。静态站点通过 GitLab Pages 部署。 |
Source: …
工作原理:流水线流程
步骤 1 – 服务级文档生成
每个微服务仓库都包含一个简单的 Yarn 脚本,用于生成文档:
{
"scripts": {
"docs": "typedoc --out docs src/"
}
}
注意: 生成的文档不会提交到服务仓库。它仅在流水线执行期间临时存在。
步骤 2 – 定时文档同步
每个服务仓库都有一个定时的 GitLab CI 流水线(通常是每晚或按需),执行以下步骤:
- 生成 – 运行
yarn docs以创建最新的 TypeDoc 文档。 - 删除并替换 – 完全删除服务之前的文档目录,并用新生成的文档替换。由于源仓库是唯一可信来源,我们直接覆盖旧文档。
- 处理竞争条件 – 在推送前执行
git pull,如有需要可进行短暂的重试间隔,以避免多条流水线同时运行时产生冲突。 - 推送 – 将文档提交并推送到 主文档仓库,放在以服务名称命名的文件夹下。
- 触发 – 推送操作会自动触发主文档仓库的重建流水线。
这样既保持了服务仓库的整洁,又能在无需人工干预的情况下确保文档始终是最新的。
步骤 3 – 中央文档构建
主文档仓库 保存 Docusaurus 配置和自定义用户文档。它的流水线在每次提交时触发,并:
- 重新构建整个站点,整合所有服务特定的 TypeDoc 文档。
- 将静态站点部署到 GitLab Pages。
- 为开发者提供一个统一的 URL,满足所有文档需求。
为什么选用 Docusaurus?
TypeDoc 生成的文档直接放在 /docs 目录下,而 Docusaurus 也要求内容位于 /docs 目录。这二者天然匹配,无需额外配置。
自定义文档支持
除了自动生成的 API 文档之外,我们还扩展系统以支持手写的用户指南、架构概览和入职材料。这些内容直接存放在主文档仓库中,作为标准的 Markdown 文件,按主题而非按服务进行组织。
为了让生成的文档更有价值,我创建了一个 自定义 TypeDoc 插件,它能够保留原始项目结构。与 TypeDoc 默认按类型(类、接口等)重新组织文件的行为不同,该插件保持目录层级与源代码仓库中完全一致。
示例:
如果源文件是 src/auth/services/UserService.ts,文档也会出现在相同的路径下。这使得查找特定文档直观易懂——开发者已经熟悉代码库中文件的所在位置,自然也知道去哪里查找对应的文档。
这种混合方式让我们兼具两者优势:从 TypeDoc 获得自动化的技术准确性,同时在需要的地方加入人工编写的解释说明。
好处
对于 AI 训练
将所有文档整合到一个统一的仓库并保持一致的格式,使我们能够向语言模型提供整个代码库的上下文。这显著提升了 AI 生成的代码建议和解释的质量。
对开发者入职
新成员现在只需一个书签。无需再询问“哪个仓库有认证文档?”,他们只需在文档站点搜索。入职时间明显缩短,因为开发者可以在不克隆数十个仓库的情况下浏览系统架构和 API 合约。
对跨团队协作
- 统一的知识库减少了重复工作。
- 团队可以直接在站点上引用彼此的 API,促进复用。
- 更新会自动传播,确保所有人使用最新信息。
TL;DR
- TypeDoc → 为每个服务生成 API 文档(不提交到仓库)。
- GitLab CI → 每晚的流水线将文档推送到中央仓库。
- Docusaurus → 将所有文档 + 自定义 markdown 聚合成可搜索的静态站点。
结果:为所有微服务文档提供唯一的真相来源,降低维护开销,加快新人上手,并为 AI 辅助开发提供更丰富的数据集。
Integration Made Easy
当团队需要集成服务或了解依赖关系时,他们不再必须立即深入源代码。集中式文档可一目了然地提供 接口契约、使用示例 和 架构上下文。
维护
文档更新会自动进行。当开发者在代码中添加 JSDoc 注释时,这些注释会在下次计划的流水线运行后出现在中心文档中。无需手动更新文档。
经验教训
冲突比想象中更简单
当多个服务同时推送文档时,你可能会担心合并冲突。解决方案很直接——删除整个之前的文档目录,直接用新的目录替换。因为源仓库是唯一的事实来源,没有必要保留或合并旧文档。来自源的最新文档始终占优。
竞争条件需要简单处理
当计划的流水线同时运行时,推送到主仓库可能会产生冲突。我们通过在每次推送前添加 git pull,并在推送失败时等待几秒后重试的机制来解决。虽然不够优雅,但非常可靠。
# Example of the push logic
git pull --rebase
git push origin main || {
echo "Push failed – retrying in 5 seconds..."
sleep 5
git push origin main
}
选择相互匹配的工具
Docusaurus 是显而易见的选择,因为 TypeDoc 的输出目录是 /docs,而 Docusaurus 正好读取 /docs。有时最好的技术决策就是那种配置最少的方案。
结构对可用性至关重要
自定义的 TypeDoc 插件能够保留仓库的目录结构,这带来了巨大的改观。开发者无需学习新的组织方式——文档就在他们预期的位置。
使用 GitLab Pages 的静态站点轻松无忧
部署到 GitLab Pages 意味着无需服务器管理、无需托管费用,并且自动提供 HTTPS。静态站点的构建时间不足两分钟,能够即时提供服务。
结论
构建集中式文档并不需要复杂的工具或昂贵的平台。借助 GitLab CI pipelines、TypeDoc、Docusaurus 和 GitLab Pages,我们创建了一个系统,能够自动维护跨整个微服务架构的完整、可搜索的文档。
这项投入立刻带来了回报,提升了新人入职速度、改进了 AI 辅助效果,并降低了开发者的挫败感。自定义的 TypeDoc 插件能够保留目录结构,使文档导航直观易用。对冲突的简易处理方式——删除并替换——消除了复杂性且没有任何副作用。最重要的是,系统能够自我维护:文档保持最新,而不会给开发团队增加负担。
如果你正为微服务之间碎片化的文档而苦恼,这种方法提供了一个实用、易于维护且能够随架构扩展的解决方案。