1. docs-as-code 到底是什么
传统文档活在代码之外的另一个宇宙:CMS、wiki 或文字处理器导出管线,有自己的登录、自己的评审流程、自己特有的缓慢腐化。docs-as-code 把文档搬回它所描述的软件所在的世界:仓库里的文件、走 pull request 的变更、走 CI 的发布。
让这一切成立的是 Markdown——因为它是开发者写起来毫无摩擦的格式,和代码旁边那个 README 同一种格式。文档变更变成 diff;错别字修复变成一行 pull request;过期页面变成一个 issue,被分配到描述的那个功能旁边。这些都不是理论——截至 2026 年,这是开发者工具文档的默认模式,围绕它的工具链已经成熟。
值得把心智模型说直白:仓库是唯一事实源,Markdown 是存储格式,文档站是构建产物。 生成器消失了,这些文件依然是完全合格的文档。
2. 三大主流生成器
以下三者都读你的 .md 文件并产出带导航、搜索和版本化的静态站点。差别在生态和扩展哲学。
Docusaurus 是 React 系选项,插件和主题生态最大。它的招牌是 MDX——可以内嵌 React 组件的 Markdown 文件——让文档页里出现交互元素。代价:MDX 文件不再是纯 Markdown,内容与 React 工具链耦合。
MkDocs,通常搭配 Material for MkDocs 主题,是 Python 系选项,以「一个下午从文件夹到精致可搜索站点」著称。配置只有一个 YAML 文件。它是三者中最接近「你的文件,只是被渲染了」的。
VitePress 是 Vue 系选项,以构建速度和极简默认样式见长。它同样支持在 Markdown 里嵌 Vue 组件,与 MDX 一样伴随可移植性代价。
搭第一个文档站时,决定因素通常是团队的技术栈语言(JavaScript 还是 Python),以及是否真的需要内嵌交互。不需要的话,三者都能用,而且你写的 Markdown 内容在三者之间完全一致。
3. 拓宽视野:五个生成器、六个维度
上面三个头牌占据了大半声量,但它们不是全部,而凭感觉选型,往往一年后就迎来一次迁移。还有两个生成器值得进入大多数候选清单。Astro Starlight 是五者中最年轻的:它构建在 Astro 的内容集合(content collections)模型之上,开箱自带文档默认项——自动生成侧边栏、上一篇/下一篇分页、内建国际化路由——本地搜索默认由 Pagefind 提供。Hugo 是另一个极端:单个 Go 二进制文件,没有任何依赖树,以几秒钟渲染超大站点著称,代价是 Go 模板——对只想调调布局的人来说,它不如一个 YAML 配置文件友好。
候选到了五个,只有锚定在「真正影响日常工作」的维度上,对比才具备决策价值,而不是营销勾选项。下面六个维度在实践中最常被用到:装什么、有什么主题、搜索怎么做、版本化怎么做、国际化怎么做、构建有多快。
| 维度 | Docusaurus | MkDocs + Material | VitePress | Astro Starlight | Hugo |
|---|---|---|---|---|---|
| 安装栈 | Node.js + React 工具链 | Python + pip | Node.js + Vite | Node.js + Astro | 单个 Go 二进制 |
| 主题生态 | 最大;npm 插件经济 | Material 是事实标准 | 精简、主见强的默认项 | 增长中;可用任意 Astro 集成 | 主题画廊巨大、质量参差 |
| 搜索 | Algolia DocSearch 或插件 | 内建客户端搜索(基于 Lunr) | 内建本地搜索;可选 Algolia | Pagefind,内建 | 自己动手:产出 JSON 索引 + JS |
| 版本化 | 一等公民,快照命令 | 经社区 mike 插件 | 自行设计方案 | 自行设计方案 | 自行设计方案 |
| i18n | 内建 locale 目录 | 插件实现 | 内建 locale 目录 | 内建 locale 路由 | 内建(内容目录 + 字符串文件) |
| 构建速度 | 中等;MDX 编译有开销 | 中小型站点快 | 非常快 | 快 | 规模化最快 |
把这张表当三组来看。安装栈和构建速度决定第一天的体验:Node 依赖树意味着文档要一起承受 npm 的升级搅动,而 Hugo 的单二进制在断网的受限 CI 机器上跑起来的行为一模一样。构建速度在站点几千页之前像个装饰性指标,过了那个量级,一分钟构建和十秒构建的差距,会直接改变大家还愿不愿意构建预览自己的改动。
主题生态和搜索决定有多少东西要自己拼。Docusaurus 背靠最大的插件经济,但 Material for MkDocs 仍是通往「看起来 professionally designed」结果的最快路径,这也是它一直是团队「第一个文档站」默认答案的原因。搜索的分化方式相同:多数生成器现在开箱自带够用的客户端搜索,而 Algolia DocSearch——对公开文档站点免费、需申请——是内建索引开始漏结果时的托管升级路径。
版本化和 i18n 是两个一年后才咬人的维度,第一天感觉不到。五者之中只有 Docusaurus 把版本化做成一等概念;MkDocs 靠社区 mike 插件补齐;VitePress、Starlight 和 Hugo 留给团队自己发明快照约定——这没问题,直到第二个版本真的发布。如果文档要服务一个 API 的多个在维护版本,那一行的权重应该完全压过主题和构建速度;如果文档只描述一个常青产品,放心按顺眼的维度选。
4. 组织页面:Diátaxis 的目录映射
在选任何生成器之前,有一个更安静、却比所有生成器都长寿的决定:一页文档是干什么用的。目前接受度最高的答案是 Diátaxis 框架,它按读者当下需要什么,把文档分成四种模式:教程(tutorial,学习导向,引导式第一次成功)、操作指南(how-to,任务导向,给已入门者的菜谱)、参考(reference,信息导向,按碎片查阅的资料)、阐释(explanation,理解导向,why 而非 how)。四种模式有不同的语气、不同的结构、不同的寿命;把它们混在一页里,是技术文档最常见的失败方式。
把框架映射到仓库几乎是机械操作,而目录树本身就变成了贡献者的分诊工具:
docs/
├── tutorials/
│ └── getting-started.md
├── how-to/
│ ├── deploy-to-production.md
│ └── rotate-api-keys.md
├── reference/
│ ├── api/
│ └── configuration.md
└── explanation/
└── why-eventual-consistency.md
这棵树在有人要写新页面的那一刻开始发挥价值。文档项目的死法都一样:一页文档卡住,因为没人知道它该放哪,写的人耸耸肩随手塞进某个地方,从此无人问津、慢慢烂掉。有了四象限目录并映射到站点侧边栏,「放哪」这个问题就有了答案,URL 结构本身就在传达页面的承诺,评审者可以对「放错位置的页面」提出异议而不必针对内容本身。
框架还裁决了文档界最古老的争论:一页文档要不要「写全」。一篇拐进架构讲解的 how-to,不如拆成两页互链——凌晨两点照着步骤操作的读者不想要一堂课,研究设计的读者不想要步骤。按模式拆分、在象限之间互链——参考页向上链到阐释,教程向前链到 how-to——每页就只需回答一个问题:它服务好自己的那个模式的读者了吗。
5. 工作流收益
生成器的重要性不及模式解锁的东西,而后者有四项足以支撑采纳。
评审:文档变更走与代码相同的 pull request 评审——理解功能的人顺手签收它的文档。版本化:文档站可以同时发布多个版本(v2.x 与 v3.x 并存),这是有长期维护版本的产品团队需要而 wiki 做不好的。搜索:生成器自动索引全站。部署:文档站在 CI 里与产品一起构建,发文档是部署流水线的一步,而不是和 CMS 管理员的一场谈判。
还有第五项收益,随 AI 时代一起到来:一个干净 Markdown 的文档仓库,恰好是 AI 管线消费效率最高的语料——按标题感知的检索、以你的文档为依据的 agent 问答、LLM 友好的结构,都是格式的免费赠品,不需要另维护一份「AI 版」。
6. 版本化:没人做预算的长期成本
这个模型里的其他成本都是一眼可见的。版本化不同:它是那个悄悄把文档维护面积放大数年的决定,值得单独算一笔账。当团队同时发布 v2 和 v3 的文档,它承诺的是让两棵平行目录树同时保持事实正确——此后每一个文档 bug,都在每棵树里各有一个住址。
第一个决定是什么时候打快照。支持版本化的生成器,做法都是把当前目录树冻结成版本副本——Docusaurus 的版本化指南记录了这个模式:一条命令把当前文档复制进 version-2.x 目录,后续编辑落入「next」树。在发布边界上打快照——旧版本行为与 main 真正分叉的时刻;只新增行为、不改已文档化行为的次要版本,忍住别打。每个快照不是一份副本,而是一个承诺。
废弃策略是第二个决定,而诚实的版本是一个数字。「文档维护最近两个大版本」是评审者可以执行的政策;「旧版本一直挂着」则会让站点积累出一个 v1 档案——自从 API 变更后就没人校验过,还在安静地对用户撒谎。给冻结版本挂上可见的横幅、把移除日期写进 changelog、到期真的删——移除一个事先告知的旧版本不会惊动任何人,而一个错误的旧版本会烧掉每一个信任它的人。
第三个决定是修复如何传播。当有人报告一个同时存在于四个已发布版本中的文档错误,务实流程是先修最新树,再 cherry-pick 到旧树——前提是事先划好哪些错误值得回移。一条站得住的线:关于已文档行为的事实性错误回移到所有支持版本;结构调整和文风修改只落最新版。没有这条线,每一次文档评审都会慢成最谨慎那个版本的速度。
最后,只为行为分叉的地方做版本化,其他地方一概不做。API 参考和配置页跨大版本确实不同,值得版本副本;概念性指南和教程通常不然,很多团队让它们单源维护、挂一条「适用于当前版本」的备注。大多数站点默认过度版本化,然后纳闷为什么维护吃掉一周一天;能活在现实里的形状,是一个小的版本化参考核心,周围环绕着一大圈不版本化、定期修剪的指南。
7. 从 Confluence 或 Notion 迁出
总有一天,搬家的理由会变得无可辩驳:装着真正文档的那个 wiki 锁在登录墙后面,外部搜索引擎看不见,任何人改起来都不经过评审——恰好是 docs-as-code 模式的反面。迁移本身是一个四阶段项目,而后悔的团队,都是把某个阶段当成可选项的团队。
-
一次性完成整体导出。 Confluence 空间可导出为 HTML 或 XML;Notion 把工作区导出成 HTML 和 Markdown 压缩包,数据库摊平成 CSV。所有导出都又慢又略带损耗,所以完整跑一遍导出,把它作为迁移的事实基底纳入版本管理,之后的增量都对它做,而不是从头反复重导。
-
把导出物清洗成纯 Markdown。 转换工具能包办大部分机械翻译,剩下的交给HTML 转 Markdown 的标准清洗套路。工具接管不了的是结构:Confluence 的布局宏塌成一锅粥,Notion 数据库丢掉视图,图片路径指向已经不存在的目录。这一步也是补 frontmatter 的时机——标题、负责人、最后校对日期——因为每个文件即将进入仓库,应该带着元数据进门。
-
趁映射还便宜时修复链接。 标题锚点在不同系统间不一致,页面标题会变成新 slug,每条指向 wiki 的内链现在都悬空了。重定向映射要在清洗阶段就建起来——旧 URL 到新 URL,作为一张表提交进仓库——而不是上线之后再补,因为还记得「A 页为什么链到 B 页」的人,正是现在还在项目上的那个人。
-
重定向、冻结、退役。 旧 wiki URL 的宿主级 301 重定向同时保住旧书签和搜索权重;旧空间转只读,挂一条指向新站的横幅;横幅上带着退役日期——因为一个无人维护的只读 wiki,正是过期答案常年复活上岸的地方。
两种失败模式解释了大多数迁移悔恨。第一种是动手之前追求完美映射——wiki 一边继续漂移,团队分析了好几个月——而可行的形状是快速、不完美的一遍过,跟着一个有主人的九十天清理窗口。第二种是不加甄别全量迁移;迁移是一生中最便宜的分诊时刻,而任何 wiki 里都有相当比例的页面,是早已死掉的项目留下的流程笔记。那些材料在搬家之前删掉,别花钱把它们搬过去。
8. 诚实的成本
构建工具链是真实存在的:一棵 Node 或 Python 依赖树、构建耗时、偶尔一次弄坏主题的升级。文档站是一个小型软件项目,应该按小型软件项目来维护。
更隐蔽的成本是扩展诱惑。当文档开始嵌组件——MDX 小部件、Vue 岛屿、自定义指令——它们就不再是可移植的 Markdown。Mermaid 图表是活下来的例外:一个 mermaid 代码块依然是纯文本,而且多数文档生成器原生渲染它。你的文件从此依赖那个生成器才能渲染,而这种格式的全部意义本来是「不依赖」。务实的一条线:95% 的页面保持纯 Markdown,把交互性花在少数几页确实比文字教得更好的地方。
最后,docs-as-code 抬高了非开发者的贡献门槛。一个活在 Google Docs 里的同事,第一次面对 pull request 会觉得充满敌意。预览部署和每页的「编辑此页」链接能缓和,但这是需要提前规划的真实采纳成本。
9. 用 CI 发布文档
docs-as-code 的日常回报在部署路径上,而最小实现装得进一个小小的 workflow 文件。典型文档站 GitHub Actions 配置有两个 job:构建 job 检出仓库、安装工具链(npm ci 或 pip install)、构建站点,构建报错或链接检查发现死链就让检查失败;部署 job 把构建产物上传到静态主机——GitHub Pages 走官方部署 action,Netlify 和 Cloudflare Pages 走各自的。整个文件就是几十行样板,团队写一次,之后几乎不再碰。
真正改变团队行为的特性不是部署,而是预览。托管平台为每个 pull request 生成一个独立的预览 URL,评审者点开链接读到的就是渲染后的页面——带导航、代码高亮和表格——而不是眯着眼睛看 Markdown diff。这一项能力对「把非开发者拉进文档评审」的作用超过任何写作规范,因为它把对方的反馈从「我想象不出这会长什么样」变成具体的、可指认的意见。
生成器选择在这里体现为构建分钟数。Hugo 站点在最便宜的 runner 上几秒建完;带 MDX 编译的重型 Node 栈可能要几分钟——一天几次构建可以忍,一天五十次就开始磨人。用什么栈都好,这里真正被固化下来的是习惯本身:发布文档是部署流水线的一步,像代码一样评审、像代码一样发布,没有单独谈判,也不用凑日历。
10. AI 检索红利
这样建起来的文档站,会悄悄变成机器的知识库。检索增强(RAG)管线沿着标题边界切块,你的标题层级就是它们的切分策略:一页有描述性 H1、每个 H2 只讲一个话题的文档,产出干净、自足的块;一页想到哪写到哪的文档,产出的块只够回答两个问题的各自一半。以产品文档为据作答的编码 agent 和客服 bot,实际上是一个文档站最苛刻的读者。
服务它们的服务人类的习惯是同一批,这正是它叫红利而不叫税的原因。描述性标题(「部署到生产环境」而非「部署」)同时喂饱搜索索引和检索切块器;每个页面在单一话题下保持连贯,让扫读的人和嵌入模型拿到同一个自足单元;坚持标准 Markdown 而非怪异指令,意味着每位读者——硅基的还是别的——渲染出的页面一模一样。「95% 页面保持纯 Markdown」的那条务实之线在这里获得第二个理由:你嵌入的每一个组件,都是检索管线读作噪音的一片页面。
到 2026 年,这些已经固化成常识,而像 llms.txt 提案这类机器可读站点摘要的约定仍在沉淀之中。不过这里经得起时间考验的一点不依赖任何具体约定:为人建的那个站,已经就是为 agent 建的知识库,不需要另维护一份 AI 版,也不需要多喂一条管线。把 Markdown 保持干净的团队,把「agent 就绪的文档」当作服务人类读者的副产品免费拿到——这是这项能力可能的最低价格。
11. 从小处开始
最小路径不需要第一天就选生成器。先把文档写成有组织的 Markdown 文件——和任何 Markdown 工作流相同的习惯:一页一个话题、一致的标题层级、页面之间的相对链接。任何生成器都能吃下这个结构;而且在文档需要公开站点之前,这个文件夹本身已经有用——可搜索、可评审、人和 AI 工具都能读。
当公开站点成为必要时,选一个匹配团队技术栈的生成器,对着你的文件夹跑它的 init 命令,提交。文档从来都是资产;站点只是一小时的配置。
12. 结语
Markdown 文档站之所以成立,是因为它把三个系统——写作、评审、发布——折叠进了一个仓库。生成器很好,但它们是可替换的;文件才是价值。按生态和团队语言选 Docusaurus、MkDocs 或 VitePress,页面保持纯 Markdown,文档就会比这些工具里的任何一个都活得久。
https://floatboat.ai/zh/blog/markdown-documentation-site
