跳转到主要内容
2 分钟阅读
指南

MDX、内容集合与作为架构的内容

为什么仅仅将 Markdown 文件拖入文件夹并不能构成一个发布系统,以及如何构建一个可扩展的发布系统。

发表于
作者 Interface Atlas Team

在 JavaScript 框架中采用 MDX 或 Markdown 时,最常见的失败模式是将其视为美化过的文字处理器。

团队配置一个解析器,将五十个 .mdx 文件拖入 /content 文件夹,然后认为他们有了一个发布系统。六个月后,他们得到了一堆没有类型约束的文章。Frontmatter 变得不一致。指南页面使用了与博客文章不同的布局,但仅仅是因为某位作者记得导入了正确的组件。重新组织文档需要对整个代码库进行正则表达式搜索。

当您的产品是阅读材料时,您的内容模型就是您的架构。

作为架构的内容的论点

在像 Interface Atlas 这样基于文件的出版物中,您必须停止将 src/content/ 文件夹视为存储桶。它是一个数据库。

既然它是一个数据库,它就需要一个模式(schema)。它需要关系。它需要约束。在 Astro 中,我们使用内容集合来强制执行这种架构。

作为发布系统的仓库

graph TD
    subgraph 数据库层
        C1[指南集合] -->|通过 Zod 验证| S1(指南模式)
        C2[术语表集合] -->|通过 Zod 验证| S2(术语表模式)
    end
    
    subgraph 图谱层
        S1 -->|topicKeys| T[主题中心]
        S1 -->|glossaryKeys| C2
    end
    
    subgraph 表现层
        T --> R1[Astro 主题路由]
        C1 --> R2[Astro 指南路由]
        C2 --> R3[Astro 术语表路由]
    end

从 Markdown 走向内容集合

无类型堆砌(失败模式)

在内容集合出现之前,框架通过 glob 导入加载 markdown 文件。您会得到作者键入的任何 frontmatter。 如果作者输入了 diffculty: hard 而不是 difficulty: Advanced,构建将会通过,但页面会悄无声息地丢失难度徽章。内容逻辑变得隐藏在试图解析损坏数据的脆弱 UI 组件中。

强类型集合(解决方案)

Astro 的内容集合通过在内容和渲染之间引入严格的边界来解决这个问题。

// src/content.config.ts
import { defineCollection } from 'astro:content';
import { glob } from 'astro/loaders';
import { z } from 'astro/zod';

export const guides = defineCollection({
  loader: glob({ pattern: "**/*.mdx", base: "./src/content/guides" }),
  schema: z.object({
    title: z.string(),
    description: z.string(),
    topicKeys: z.array(z.string()), // 强制执行图谱关系
    difficulty: z.enum(["Foundation", "Intermediate", "Advanced"]), // 防止拼写错误
  }),
});

这段代码教导了一个架构上的推论:内容错误现在是构建错误。 如果作者忘记了 topicKeys 数组,Astro 的构建将会失败。网站无法在损坏的状态下部署。

Frontmatter 是关系模式

一旦你有了强类型集合,Frontmatter 就不再仅仅是一个放标题的地方。它变成了构建你的内容图谱的关系模式。

在 Interface Atlas 中,我们不会在 MDX 文件的底部硬编码“相关指南”。我们使用 frontmatter 键:

---
title: "信息架构"
topicKeys: ["architecture", "seo"]
glossaryKeys: ["taxonomy"]
relatedGuideKeys: ["what-frontend-architecture-really-is"]
---

因为这是强类型的,路由层可以自动生成相关链接、主题中心标签和术语表工具提示。

基于 Git 的编辑工作流

当仓库就是 CMS 时,Git 工作流就是编辑工作流。

  1. 起草: 作者创建一个分支并编写一个 MDX 文件。
  2. 审查: Pull Request 变成了编辑审查。审阅者可以像评论代码一样评论散文。
  3. 验证: CI/CD 运行 Astro 构建。Schema 验证 frontmatter,MDX 验证组件语法。
  4. 发布: 合并到 main 分支会触发到边缘节点的静态部署。

当团队试图强迫非技术编辑在没有像 Decap CMS 这样的工具的情况下直接使用 GitHub 时,或者当 MDX 文件被复杂的 JSX 严重污染以至于作者无法再阅读文本时,这个工作流就会失败。

当 MDX 不够用时

MDX 是一种混合媒介。它允许您将复杂的交互式组件直接嵌入到长篇文本中。但你必须知道何时停止。

如果一个 MDX 文件包含 40 行文字和 300 行复杂的 React 状态管理,你就越界了。内容现在屈从于应用程序逻辑。

规则: 保持 MDX 文件专注于阅读。如果一个交互式小部件需要复杂的本地状态,请将其抽象为一个 Island(群岛)组件,并从 MDX 文件向其传递简单的 props。

相关指南和术语

探索支持系统: