跳至正文
Tooling — MDX 入门:组件化写作、Astro 集成与 Obsidian 支持边界

MDX 入门:组件化写作、Astro 集成与 Obsidian 支持边界

AI 参与说明(Agent:Codex):本文根据 MDX、Astro、Obsidian 官方资料及社区插件作者文档辅助撰写与校验,资料整理于 2026-09-08。工具选择与内容组织建议是本文的工程判断;插件能力依据其公开说明,未进行 Obsidian 插件安装实测。运行记录:模型 gpt-6-astra,reasoning effort ultra,执行入口 Codex Desktop,提供方 openai,CLI 版本 0.153.4(不代表桌面 App 版本)。

文章需要直接调用组件、根据数据生成内容时,MDX 很有价值;以文字、图片和普通代码示例为主时,Markdown 仍然足够。 Astro 提供正式的 MDX 集成,Obsidian 则主要依赖社区插件补充编辑和预览能力。选择格式时,需要同时考虑发布系统与日常写作工具。

先认识下面几个词。中文名称用于导读,后文保留对应的英文名称。

英文术语中文名称简要解释
MDXMDX可以在 Markdown 正文中使用组件和 JavaScript 的内容格式
JSXJavaScript 语法扩展用类似 HTML 的标签描述界面,例如 <Notice />
JavaScript expressionsJavaScript 表达式会产生一个值的代码,例如 price * count
ESMECMAScript 模块用 import 和 export 组织、共享代码与数据的模块机制
props组件属性调用组件时传入的数据,例如提示框的标题
hydration水合为服务端已生成的界面接上浏览器中的组件逻辑与状态
frontmatter前置元数据写在正文前的标题、日期等信息,常用 YAML 表示
CommonMarkCommonMark对 Markdown 基础语法的明确规范
GFMGitHub 风格 Markdown在基础 Markdown 上补充表格、任务列表等语法的方言

MDX combines Markdown content with JSX, JavaScript expressions, and ESM. Its integration compiles the document into a JavaScript module that exports a component. 普通段落继续用 Markdown 写,需要特殊展示的地方再调用组件;整篇内容因此也能作为组件被其他页面引用。What is MDX? · Using MDX

MDX 比传统 Markdown 多了什么

这里的“传统 Markdown”指 CommonMark 一类正文语法。具体网站可能通过插件、模板或 HTML 获得更多能力,不能把某个渲染器的限制当成 Markdown 网站的共同限制。

能力Markdown 正文MDX 正文
标题、段落、列表、链接、图片、代码块基础能力继续支持常见写法
插入 HTML规范允许,具体平台可能过滤HTML 风格标签按 JSX 规则解析
调用项目组件需要网站另行提供模板或扩展语法可以直接写 <Notice title="提示" />
根据变量计算正文不是 Markdown 自身的语义可以写 {price * count}
导入组件、共享数据、其他文档不是 Markdown 自身的模块能力可以用 import / export
用数组生成重复内容、按条件展示需要外部模板或程序处理可以在表达式中使用 .map()、条件运算符等
把全文当作组件复用需要网站额外封装编译后的内容本身就是组件

例如,一组参数说明需要在十篇文档里保持一致,可以让十篇 MDX 调用同一个组件,并传入不同的 props。调整结构时修改组件即可。相应代价是这些文章开始依赖组件接口,组件重命名、参数变化或删除也会影响内容构建。这是由模块依赖关系带来的工程取舍。Using MDX:Components

交互不是文件扩展名自动带来的。 MDX 让交互组件进入文章成为自然的写法,但按钮状态、图表筛选和输入反馈仍由组件实现,浏览器执行方式由所用框架决定。MDX 也不只限于 React;支持哪些组件以及怎样运行,应看对应集成。MDX:How MDX works

这些常见能力并非 MDX 独有

GFM 表格、任务列表、代码高亮、数学公式和 Mermaid,并不是“用了 MDX 才能有”的功能。它们分别涉及 Markdown 方言、渲染插件或页面脚本,普通 Markdown 网站也可以提供。

MDX 核心默认不启用 GFM;YAML frontmatter 也需要插件或框架提供支持。Astro 的 MDX 集成会继承相应的 Markdown 配置,并提供 frontmatter 支持。因此要区分 MDX 格式能力与当前网站已经配置的能力。MDX:GFM · MDX:Frontmatter · Astro:Markdown content

已有 Markdown 文章能显示 Mermaid,不构成迁移 MDX 的理由;需要把一个可调参数的演示组件嵌入论述,才更能发挥 MDX 的作用。

先在浏览器中试一个完整示例

打开 MDX Playground,将以下内容放入编辑区,可以同时观察渲染结果与生成的 JavaScript。示例没有外部组件或依赖导入。

mdx
export const lesson = {
  title: 'MDX Lab',
  minutes: [10, 15, 20],
}

export function Badge({children}) {
  return <strong style={{color: '#08745b'}}>{children}</strong>
}

# {lesson.title}

Total: {lesson.minutes.reduce((sum, value) => sum + value, 0)} minutes.

Status: <Badge>Ready</Badge>

<ul>
  {lesson.minutes.map((minutes, index) => (
    <li key={index}>Part {index + 1}: {minutes} minutes</li>
  ))}
</ul>

预期显示标题 MDX Lab、总时长 45 minutes、绿色的 Ready,以及三个分别为 10、15、20 分钟的列表项。把数组中的 20 改成 30,总时长会变成 55 minutes。

这里同时出现了三个新增能力:ESM 保存共享数据和组件定义;JavaScript expressions 计算总时长、生成列表;JSX 调用 Badge 并把 Ready 作为 children 传入。代码围栏中的 MDX 只展示源码,实际计算发生在 MDX 编译并运行之后。

写在同一文件里的 Badge 适合演示。正式项目可将组件移入工程,再在 MDX 中导入。复杂行为和样式集中到组件,正文便能继续围绕解释与例子展开。

MDX 怎样变成网页

下面以包含 client:visible 组件的 Astro 静态页面为例。构建先生成 HTML 和该组件所需的 JavaScript,浏览器先显示内容,等组件进入视口后再加载组件 JavaScript。普通静态内容不需要最后两步。

flowchart TD
    A["MDX 正文<br/>与组件 import"] --> B["Astro 编译<br/>与解析依赖"]
    B --> C["生成 HTML 与<br/>组件 JavaScript"]
    C --> D["浏览器显示<br/>正文与初始界面"]
    D --> E["组件进入视口<br/>加载 JavaScript"]
    E --> F["完成 hydration<br/>响应组件交互"]

Astro renders UI framework components to HTML by default. A client:* directive controls when a component’s JavaScript is sent to the browser and hydration begins. 因此,在 MDX 中调用一个 React 组件,并不意味着整个页面都会变成需要大量 JavaScript 的客户端应用。Astro:Front-end frameworks

例如,已有一个正确导入的 React Counter 组件时,下列是 Astro MDX 的调用片段:

mdx
import Counter from '../components/Counter.jsx'

<Counter />

<Counter client:load />

<Counter client:visible />

它们依次表示:仅生成初始 HTML;页面加载时加载并执行组件 JavaScript;进入视口时加载并执行。片段需要工程已安装 React 集成且提供 Counter.jsx,不包含组件实现。client:* 是 Astro 的指令,不能据此推断其他 MDX 环境或 Obsidian 插件有同样行为。Astro:Client directives

想先体验组件与正文共存,可以打开本站 Labs,操作 HeroUI 示例,再看同页的 Astro 静态提示框。这个页面由站点原生 MDX 组织内容;它展示的是具体组件的能力,MDX 负责把组件嵌入文章结构。

Astro 的支持具体到哪一步

Astro 通过官方 @astrojs/mdx 集成支持 .mdx 页面、组件导入和内容集合中的 MDX。需要使用 React、Svelte 等组件时,还要接入相应框架的 integration。普通 .astro 组件可直接参与 Astro 的 MDX 渲染。Astro:MDX integration · Astro:Content collections

以下是一个已存在的 Astro 工程中的最小接入示例,演示静态组件与 Markdown 混排。先使用官方命令添加 MDX integration;已有主题或 integration 已经添加 MDX 时,应检查配置,避免重复注册。

sh
npx astro add mdx

基础配置的关键部分如下。已有工程应把 mdx() 合并进现有 integrations,保留其他配置。

js
// astro.config.mjs
import {defineConfig} from 'astro/config'
import mdx from '@astrojs/mdx'

export default defineConfig({
  integrations: [mdx()],
})

页面外壳 src/layouts/Article.astro:

astro
---
const {frontmatter} = Astro.props
---
<!doctype html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>{frontmatter.title}</title>
  </head>
  <body><main><slot /></main></body>
</html>

复用组件 src/components/Notice.astro:

astro
---
const {title} = Astro.props
---
<aside aria-label={title}>
  <strong>{title}</strong>
  <slot />
</aside>

正文 src/pages/mdx-demo.mdx:

mdx
---
title: MDX with Astro
layout: ../layouts/Article.astro
---

import Notice from '../components/Notice.astro'

export const total = 2 + 3

# MDX with Astro

Computed total: {total}.

<Notice title="Build-time content">

This paragraph supports **Markdown** inside an Astro component.

</Notice>

在该工程执行 npx astro dev 后访问 /mdx-demo/,应看到计算结果 5 和包含加粗文字的提示框。执行 npx astro build 后,这些内容直接存在于 HTML 中;示例没有需要 hydration 的组件。MDX 的 YAML 区域保存 frontmatter,JavaScript 的 import / export 写在该区域之外。这里的 layout 是 src/pages/ 独立内容页的约定,使用内容集合时不能假定它自动套用布局。Astro:Markdown layouts

上述 Astro 示例以 Node.js 26.0.0、Astro 7.3.1、@astrojs/mdx 8.0.0 完成本地构建与 HTML 校验;这是验证所用组合,不是最低版本要求。前面的独立 MDX 示例另外使用 @mdx-js/mdx 3.1.1 编译和渲染校验。

外部内容仓库还需要导入链路

Astro 支持 MDX,不代表任意从磁盘读取的 .mdx 字符串都会自动编译。若内容管线只是“读取文件 → 普通 Markdown 渲染 → 插入 HTML 字符串”,就没有完成组件导入、依赖解析与 MDX 模块渲染。

对于独立内容仓库,接入时通常要明确三件事:让文件进入 Astro 支持的编译与路由机制;约定组件可用的稳定导入路径;保留原有标题、链接、目录与搜索所需的静态内容。这是根据 MDX 编译模型得出的工程要求,不能仅靠把 .md 重命名为 .mdx 完成。MDX:Using MDX · Astro:Content collections

Obsidian 的支持要分层看

Obsidian 的官方文件格式列表将 Markdown 对应为 .md,没有把 .mdx 列为原生 Markdown 格式;额外文件类型可以通过社区插件扩展。Obsidian:Accepted file formats

截至整理日期,以下插件提供的能力不同:

使用层次支持情况实际边界
创建和编辑 .mdxEdit MDX 可以像 .md 一样创建、编辑作者明确说明不负责 MDX 预览
编译与部分 JSX 预览MDX Preview 可编译 MDX,提供 JSX 和 Code Hike 预览使用插件自己的渲染环境
从应用工程导入的自定义 React 组件MDX Preview 无法解析应用自己的组件显示带说明的占位内容,不能还原站点组件效果
Astro 组件、样式和 client:* 行为需要实际 Astro 工程验证不能由插件中的预览成功推断站点效果一致
Backlinks、Graph、搜索及其他插件协作需要按文件类型与插件组合逐项确认能打开文件不等于知识库功能与 .md 完全等价

前两项分别见 Edit MDX 作者说明 与 MDX Preview 作者说明,它们也已列入 Edit MDX 社区目录 和 MDX Preview 社区目录。MDX Preview 会在带有会话确认的隔离 iframe 中执行 MDX JavaScript;这进一步说明它提供了自己的运行环境,并非复用了 Astro 项目的完整构建配置。

关于索引,Anything as Markdown 将非 .md 文件的索引支持标为实验性能力。因此,若依赖 Obsidian 的链接关系、搜索和其他插件,应先用少量样本检查这些具体功能,不能只看扩展名是否已经出现在文件列表中。Anything as Markdown 作者说明

比较稳妥的写作分工是:Obsidian 处理文字与笔记组织,代码编辑器维护组件,Astro 预览确认最终网页。 如果日常写作高度依赖 Obsidian 的完整 Markdown 体验,保留大部分文章为 .md,仅让确实需要组件的页面使用 .mdx,通常更容易维护。

从 Markdown 迁移时,容易踩哪些坑

MDX preserves much of Markdown’s syntax, but it is not a drop-in replacement for every Markdown file. In particular, < and { can start JSX or JavaScript syntax. 普通文稿里能直接显示的字符,到了 MDX 中可能触发解析错误。MDX:Troubleshooting

原有写法或习惯迁移时的处理
正文里直接写花括号、模板占位符使用行内代码、代码块或转义,避免被当作 JavaScript expressions
HTML 的 <br>、未闭合标签、随意嵌套按 JSX 规则自闭合或正确配对,例如 <br />
<!-- comment -->改为 MDX 的 {/* comment */}
在 YAML frontmatter 中写 JavaScript将 import / export 移到 frontmatter 之外
缩进表示代码块改用围栏代码块,避免与 JSX 排版缩进混淆
旧模板、shortcode、特殊内部链接语法为 MDX 配置相应转换,不能假定原 Markdown 插件都能原样复用

在 React JSX 中为 HTML 元素设置 CSS class 时使用 className;自定义组件接受哪些 props 则由组件接口决定。迁移旧 HTML 时,要同时检查 MDX 语法与目标组件所接受的属性,不能将 React 的规则推广到所有框架集成。MDX:Syntax · Astro:Framework component props

正文中写 const x = 1 不会因为扩展名是 .mdx 就自动变成模块声明;需要使用合法的 ESM 导出、组件内部代码或表达式。较长逻辑放回组件或普通模块,文章只保留理解示例所需的调用。

还有一个实质性的边界:MDX 内容可以执行代码。从不可信来源收集文章时,不能把直接编译并执行任意 MDX 当作普通文本渲染。@mdx-js/mdx 官方文档明确提醒,evaluate 会执行 JavaScript;内容来源及可导入模块需要按代码依赖管理。MDX:Security

哪些文章值得采用 MDX

下面是基于写作与维护成本的选择建议。

内容目标建议
长期知识笔记、普通教程、图文记录优先 Markdown,便于在不同工具间阅读和编辑
只需要公式、Mermaid、代码高亮先检查现有 Markdown 渲染能力
需要嵌入可操作的图表、参数实验或组件示例考虑 MDX,让演示与解释位于同一阅读位置
多篇文章共用提示框、对比卡片或数据视图考虑 MDX,并维护稳定的组件 props
演示复杂、可以独立使用或需要单独布局保留 Markdown 文章,链接或嵌入独立演示页也很合适

推荐让 .md 与 .mdx 按文章需要共存。组件接口尽量小而稳定:文章提供标题、参数和少量数据,组件负责展示及行为。这样既能利用 MDX 的组合能力,也能控制内容对工程细节的依赖。

相关入口

本文共 3889 字,创建于 Sep 8, 2026

相关标签:Frontend, Tools, ByAI

博客助手

正在打开博客助手…