MDX 编译、组件边界与内容安全手册
MDX 不是“支持组件的 Markdown”这么简单。核心编译器会把 MDX 转成 JavaScript,正文中的 JSX、导入导出、remark/rehype 插件和组件实现都进入执行链。官方 @mdx-js/mdx 当前主线是 ESM 包,适合通过站点或 bundler 集成;这意味着安装方式、Node 运行时和依赖锁文件都属于文档架构的一部分。
先确认为什么需要 MDX
只有当页面确实需要交互组件、可复用演示或由代码驱动的可视化时,MDX 才值得引入。普通说明文档继续使用 Markdown,能减少编译依赖和攻击面。内容来源如果包含外部投稿、用户输入或未经代码评审的同步数据,不应直接进入 MDX 编译器,因为它面对的是潜在可执行内容,而不是无害文本。
项目合同需要定义允许导入的模块、可用组件、插件清单、资源目录和编译目标。组件通过集中映射暴露给正文,避免作者从任意包导入实现。这样既能控制设计一致性,也能让依赖审计知道实际执行了什么。
import {Callout} from './components/Callout.js'
export const mdxComponents = {
Callout,
a: SafeExternalLink,
img: RepositoryImage,
}建立可重复的编译基线
安装或启用 MDX 时,优先选择现有框架的官方集成。核心编译器适合需要完全控制的构建脚本,bundler 项目则使用对应集成,避免手写加载链。依赖版本通过锁文件固定,Node 版本通过项目配置固定,插件参数也应进入代码评审。
import {compile} from '@mdx-js/mdx'
import remarkGfm from 'remark-gfm'
const result = await compile(source, {
remarkPlugins: [remarkGfm],
development: false,
jsxImportSource: 'react',
})配置影响不能只用页面截图判断。开启一个插件可能改变标题、表格、原始 HTML或 URL 处理;替换 JSX runtime 可能改变生成模块和服务端渲染行为。仓库应保存最小夹具和编译快照,升级时同时检查生成代码、最终 HTML 与客户端 hydration。
正向与反向实验要证明执行边界
正向验证至少包含普通 Markdown、一段受控 JSX、一个由组件映射提供的组件和一项静态资源。构建成功后,确认服务端输出存在、浏览器没有 hydration 错误、交互行为可用且无额外网络请求。CI 保存构建日志和输出摘要,不上传包含内部内容的完整调试包。
反例可以尝试导入未授权模块、引用不存在的组件、传入非法属性和制造 ESM 语法错误。预期结果是编译阶段明确失败,而不是在生产浏览器里才报错。若系统允许动态内容,还要证明它先经过普通 Markdown 或结构化数据通道,不能被拼接成 MDX 后执行。
故障定位按解析、转换、打包和运行四层进行。解析错误关注源码位置;插件错误关注处理顺序与 AST;打包错误关注 ESM、别名和服务端依赖;运行错误关注组件属性和 hydration。保留最小输入与生成模块,比反复调整页面模板更容易得到可复现证据。
插件链就是供应链
remark、rehype 与 recma 插件可以读取和改写语法树,有些还会访问文件系统或网络。插件安装前需要检查维护状态、依赖树和实际权限,升级时独立评审生成差异。构建服务只读取文档目录和明确的资源目录,禁止把部署 Token、云凭证或生产数据注入 MDX 编译进程。
原始 HTML 和危险 URL 必须按发布场景处理。即使编译器本身不执行某段 HTML,最终浏览器仍可能解释它。对不可信内容,应在进入 MDX 之前降级为安全数据,或使用明确的白名单渲染器;不要把“关闭某个插件”误认为完整安全模型。
项目接入与发布治理
MDX 页面与组件代码在同一个 PR 中评审。正文 owner 负责事实与表达,组件 owner 负责 API、无障碍和运行成本,平台 owner 负责编译器与插件。分工不是增加审批,而是避免文章作者在不知情时承担前端运行时责任。
容量治理要看编译时间、客户端 JavaScript、组件复用率和缓存命中。能在构建期变成静态 HTML 的内容不应强制进入客户端包;大型交互演示要延迟加载,并为无 JavaScript 环境保留可读替代。成本失控通常不是文章数量造成,而是每页携带了不必要的运行时。
清理、回滚与迁移
移除组件前先查询所有 MDX 引用,提供等价替换或静态降级,再删除实现。清理插件时重新构建全部夹具,确认标题、链接和代码高亮没有无声变化。若升级造成大面积生成差异,回滚锁文件与集成配置,并保留失败输入用于后续兼容测试。
迁移到不支持 MDX 的平台时,先把组件分为静态表达、可预渲染结果和必须保留的交互能力。静态内容转换成标准 Markdown 或 HTML,交互结果导出可读快照,真正需要运行的组件迁移到独立应用并通过链接引用。恢复目标是内容仍可读、关键证据仍可查,不是强迫新平台复制旧运行时。
MDX 的长期价值在于受控地连接内容与组件,而不是把每篇文档变成应用。边界清楚时,它能让技术说明更可验证;边界模糊时,它会把内容仓库变成隐蔽的软件供应链。
