一个文档工具差点让我通宵,但值了
上周五晚上十点半,我合上 MacBook,长舒一口气——终于把团队的前端文档体系搭好了。窗外北京的晚风裹着初夏的燥热吹进来,地铁末班车早就没了,只能打车回昌平。这事儿得从我们实验室最近接的一个校企合作项目说起。
我是北邮软件工程研二的学生,平时在导师的横向项目组里搬砖。最近在做一个企业级数据可视化平台,前后端分离架构,我主要负责前端模块和一部分数据采集逻辑(对,就是写爬虫)。团队不大,五个同学加两个校外工程师,大家各自为战,代码风格不统一不说,最头疼的是——没人写文档!
产品经理甩过来一堆 Figma 设计稿,后端接口文档三天一变,测试同学天天在群里吼:“这个字段到底叫 user_id 还是 userId?” 我一度怀疑自己不是在做开发,而是在玩“大家来找茬”。
为什么文档工具成了救命稻草?
事情的转折点发生在双11前夕的一次线上事故。我们有个内部爬虫服务,用来抓取公开的行业数据,供前端展示趋势图。某天凌晨三点,运维大哥把我从梦中叫醒:“你那个 /api/scrape 接口挂了,返回 500,前端图表全白屏!”
我迷迷糊糊打开终端,发现是爬虫依赖的某个第三方库升级了 API,但我们没人知道这个接口是谁写的、怎么用、依赖哪些环境。最后花了两小时翻 Git 提交记录才定位到问题。那一刻我下定决心:必须搞一套自动化的文档工具链,不然迟早被产品经理和运维联合“制裁”。
选型:Docusaurus vs VuePress vs 自研?
作为 Mac 党(Windows 只在我需要测 IE 兼容性时才会开机),我倾向用现代、轻量、支持 Markdown 的工具。调研了一圈,主要考虑三个方向:
- VuePress:团队里有人熟悉 Vue,上手快。
- Docusaurus:Meta 出品,支持多版本、国际化,React 生态友好。
- 自研脚本 + GitHub Pages:灵活,但维护成本高。
考虑到我们前端主框架是 React,且未来可能对接国际客户,最终选了 Docusaurus v3。它不仅能写静态文档,还能集成 API 自动生成、版本切换,甚至支持博客模式——正好可以把我们的技术方案沉淀下来。
npx create-docusaurus@latest my-docs classic --typescript
cd my-docs
npm start
三行命令跑起来,localhost:3000 上一个清爽的文档站点就出现了。那一刻我甚至有点感动:原来写文档也可以这么优雅。
实战:把爬虫接口文档化
我们的爬虫服务是用 Python FastAPI 写的,但前端需要知道每个接口的请求参数、返回结构、错误码。传统做法是手写 Swagger,但更新不及时,而且和前端文档割裂。
我灵机一动:能不能让前端文档站直接“吃掉”后端的 OpenAPI spec?
Docusaurus 有个插件叫 @docusaurus/plugin-content-docs,配合 redoc 或 swagger-ui 就能嵌入交互式 API 文档。但我更进一步——用脚本每天凌晨自动拉取后端的 /openapi.json,转换成 Markdown 表格,放进 Docusaurus 的 docs 目录。
关键脚本如下(简化版):
// scripts/generate-api-docs.ts
import { writeFileSync } from 'fs';
import fetch from 'node-fetch';
async function fetchOpenAPI() {
const res = await fetch('http://internal-api.example.com/openapi.json');
const spec = await res.json();
let md = '# 爬虫服务 API 文档\n\n';
for (const [path, methods] of Object.entries(spec.paths)) {
for (const [method, details] of Object.entries(methods)) {
md += `## ${method.toUpperCase()} ${path}\n\n`;
md += `${details.summary || ''}\n\n`;
// 生成请求参数表格
if (details.parameters) {
md += '| 参数 | 类型 | 必填 | 说明 |\n|------|------|------|------|\n';
for (const param of details.parameters) {
md += `| \`${param.name}\` | \`${param.schema?.type}\` | ${param.required ? '是' : '否'} | ${param.description || ''} |\n`;
}
md += '\n';
}
}
}
writeFileSync('docs/api/crawler.md', md);
console.log('✅ API 文档已更新');
}
fetchOpenAPI().catch(console.error);
然后在 package.json 里加个定时任务:
{
"scripts": {
"docs:api": "tsx scripts/generate-api-docs.ts",
"docs:build": "npm run docs:api && docusaurus build"
}
}
现在,只要后端改了接口,第二天早上我们的文档站就会自动同步。测试同学再也不用问字段名了——直接看文档就行。
前端组件文档也不放过
光有 API 不够,我们的 React 组件库也得文档化。以前都是靠 Storybook,但部署麻烦,还得单独维护。
Docusaurus 支持 MDX(Markdown + JSX),这意味着我可以在文档里直接写 React 组件示例:
---
title: DataChart 组件
---
import DataChart from '@site/src/components/DataChart';
## 基础用法
展示行业趋势数据:
<DataChart data={sampleTrendData} height={300} />
## Props 说明
| 属性 | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| data | `Array<{x: string, y: number}>` | - | 图表数据源 |
| height | `number` | 200 | 容器高度 |
本地开发时,改一行代码,文档里的示例实时刷新。所见即所得,简直不要太爽。关键是,所有文档和代码都在同一个 Git 仓库,PR 里顺手更新文档成了团队新默契。
踩过的坑和血泪教训
当然,过程没那么顺利。分享几个踩过的坑:
Mac 和 Windows 路径问题
我们有个同学用 Windows 测试,结果scripts/generate-api-docs.ts里的路径分隔符炸了。后来统一用path.join()解决。Docusaurus 构建慢
随着文档增多,docusaurus build要 2 分钟。我加了缓存和增量构建,还配置了 CI/CD 只在 main 分支 push 时才全量构建。权限控制缺失
内部 API 文档不能公开。我们临时方案是部署到内网 Nginx,加 basic auth。长期打算接入公司 LDAP。产品经理又改需求了
上周 PM 说:“能不能加个搜索功能,按业务场景查接口?” 好吧,Docusaurus 默认 Algolia 搜索要申请 key,我干脆自己用 Fuse.js 实现了个本地模糊搜索,50 行代码搞定。
效果:从混乱到有序
上线一个月,效果立竿见影:
- 新成员入职,第一天就能看懂整个系统接口和组件用法
- 跨团队协作时,直接甩文档链接,沟通效率翻倍
- 最重要的是——再也没人在凌晨三点打电话问我接口字段了!
我们甚至把这套文档体系推广到了实验室其他项目组。导师看了都说:“你们这届研究生,有点东西。”
最后一点碎碎念
说实话,写文档这件事,在很多程序员眼里是“脏活累活”。但当你经历过一次线上事故、被测试追着问三天、或者看着实习生一脸迷茫地翻你半年前的代码时,就会明白:好的文档不是成本,而是杠杆。
工具只是手段,核心是建立一种“文档即代码”的文化。我们现在的 PR 模板里强制要求:如果涉及接口或组件变更,必须附带文档更新。虽然一开始有人抱怨,但现在大家都习惯了——毕竟,谁不想少加班呢?
对了,如果你也在用 Docusaurus 或类似工具,欢迎交流!顺便求推荐好用的 API 文档 diff 工具,我想监控接口变更……(别问,问就是被后端兄弟坑怕了)
工具栈小结:
| 用途 | 工具 | 备注 |
|---|---|---|
| 文档站点 | Docusaurus v3 | React + TS,支持 MDX |
| API 同步 | 自研 Node 脚本 | 每日 cron job |
| 部署 | GitHub Pages + 内网 Nginx | 公开文档走 GH,内部走内网 |
| 搜索 | Fuse.js | 轻量级本地模糊搜索 |
| 版本管理 | Git + Docusaurus 版本功能 | 对接产品迭代周期 |
写完这篇,地铁已经到西二旗了。明天还要改爬虫的反反爬策略,但至少,文档这块心病算是放下了。

评论 0