用 Astro + MDX 构建可维护的文档组件系统
复盘我在本站搭建一套可复用文档组件的过程,覆盖 Callout、Steps、StatGrid、CompareTable 等组件的设计取舍和 MDX 全局注入方案。
为什么不只是写 Markdown
纯 Markdown 写技术文档够用,但写到我自己的知识库和复盘文章时,会遇到几个反复出现的需求:
- 想在一段说明旁边加一个醒目的“注意”框
- 想把操作步骤编号化,而不是用
1. 2. 3.凑数 - 想放一组统计数字,而不是手写表格
- 想做两个方案的对比表,高亮推荐列
这些用纯 Markdown 都能做到,但每次都要手写 HTML 或重复粘贴,维护成本高。MDX 的价值在这里:让文档复用组件,而不是复制粘贴 HTML。
我设计的组件清单
9文档组件
0需要 import 的次数
1配置入口
100%黑夜模式覆盖
这些组件全部放在 apps/web/src/components/docs/ 下,通过 astro.config.mjs 的 mdx({ components }) 全局注入,任何 .mdx 文件直接用,不用 import。
关键组件:Callout
关键组件:Steps
把操作流程编号化,比手写有序列表更稳定:
- 在
astro.config.mjs的mdx()配置里传入components对象 - key 是组件名,value 是组件路径(相对于项目根)
- 在任意
.mdx文件里直接用<Callout>,无需 import - 运行
pnpm build验证全局注入生效
关键组件:CompareTable
做技术选型时,对比表比文字描述清晰得多:
| 能力 | 全局注入 | 手动 import |
|---|---|---|
| 书写成本 | 零 import | 每篇都要 import |
| 一致性 | 统一入口管理 | 容易漏 import |
| 可发现性 | 需要文档清单 | 看文件头就知道 |
| 适用场景 | 站点级组件库 | 一次性组件 |
为什么选全局注入而不是手动 import
对于一个站点级的文档组件库,全局注入的书写成本最低。代价是可发现性弱——读者不知道有哪些组件可用。所以我用一篇专门的文章(就是这篇)作为组件清单的入口。
这套组件后续会怎么演进
这套组件同时是未来 CMS 动态内容 Block 渲染层的基础。当 CMS 接入后,后台存的是结构化 Block(callout / code / audio 等),前台用 BlockRenderer 按 type 映射到这些组件。所以现在把组件设计好,后面 CMS 接入时直接复用,不用重写。