BetterLink Logo 比邻
切换语言
切换主题

Astro Markdown进阶:7个实用技巧让你的博客专业10倍

Astro MDX 高级用法示意图

你刚用 Astro 搭好博客,开始写第一篇技术文章。想要高亮代码的某一行?不行。想加个可折叠的警告框提醒读者注意事项?做不到。想在算法讲解里加个数学公式?完全没思路。

我也遇到过这种尴尬。用纯 Markdown 写了几篇文章后发现,能表达的东西太有限了。看别人的技术博客,代码块可以标注重点、可以展示代码改动前后的对比,文章里还能嵌入交互式的组件,自己却只能干巴巴地贴代码。

好在 Astro 提供了 MDX 这个”增强版 Markdown”。说白了,MDX 让你在写文章的时候可以用组件、可以写 JSX,能做的事情一下子多了好几倍。

这篇文章我会分享 7 个 Astro Markdown/MDX 的进阶用法,从最基础的环境配置到代码高亮、自定义组件、数学公式、流程图,每个技巧都配了完整的代码和配置步骤。读完这篇,你的技术博客能从”能看”升级到”专业”。

第一部分:基础升级 - 从 Markdown 到 MDX

为什么要用 MDX?

Markdown 和 MDX 的区别,其实就像自行车和电动车——都能骑,但体验完全不同。

纯 Markdown 只能写文本、代码块、图片这些静态内容。你想加个提示框?得用 HTML 硬编码。想在文章里嵌入一个可交互的组件?基本没戏。

MDX 就不一样了,它是”Markdown + JSX”的结合体。你可以:

  • 导入和使用组件:直接在 .mdx 文件里 import 任何 Astro 组件或 React/Vue 组件
  • 写 JSX 表达式:在文章里用 {variable} 插入变量,甚至写循环和条件判断
  • 自定义元素样式:把标准的 <h1> 替换成你自己的样式化组件

举个具体例子。你想在文章里加个警告框,用纯 Markdown 得这样写:

<div class="warning">
  <p>注意:这个操作会删除所有数据!</p>
</div>

用 MDX 就能这样:

import Alert from '@/components/Alert.astro';

<Alert type="warning">
  注意:这个操作会删除所有数据!
</Alert>

看出区别了吗?MDX 让你的文章更像是在”组装积木”,而不是”写代码”。

5分钟配置 MDX 环境

配置 MDX 其实超简单,三步搞定。

第一步:安装集成包

打开终端,在你的 Astro 项目里运行:

npx astro add mdx

Astro CLI 会自动帮你安装 @astrojs/mdx 并更新配置文件。这个命令会问你几个问题(要不要更新配置、要不要安装依赖),全部选 Yes 就行。

第二步:验证配置

装完后,打开 astro.config.mjs,应该能看到这样的代码:

import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';

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

如果没有自动添加,手动加上就行。

第三步:测试 MDX 是否生效

src/pages/src/content/ 目录下创建一个 test.mdx 文件:

---
title: 测试MDX
---

# 这是 MDX 测试

普通的 Markdown 文本。

export const greeting = "你好";

现在可以用变量了:{greeting}

<div style="padding: 1rem; background: #f0f0f0;">
  这是一个 JSX 元素
</div>

运行 npm run dev,访问对应页面,如果能看到变量和 JSX 元素正常显示,说明 MDX 已经配置成功了。

关于 .md 和 .mdx 文件的共存

装了 MDX 集成后,你的 .md 文件还是正常工作的,不用担心。Astro 会根据文件扩展名自动选择处理方式:

  • .md 文件:按标准 Markdown 处理
  • .mdx 文件:按 MDX 处理,支持组件和 JSX

我的建议是:普通文章用 .md,需要用组件的文章用 .mdx。不是所有文章都需要 MDX 的能力。

第二部分:代码高亮的进阶技巧

配置代码高亮主题(Shiki)

Astro 默认用 Shiki 做代码高亮,这已经很不错了。但默认主题是 github-dark,你可能想换个更符合自己博客风格的。

Shiki vs Prism 该选哪个?

老实讲,我推荐 Shiki。它是 Astro 默认的方案,支持 100 多种编程语言和主题,而且是服务端渲染的,不需要加载额外的 JavaScript。Prism 也不错,但需要引入 CSS 文件,配置相对麻烦一点。

切换内置主题

打开 astro.config.mjs,在 markdown 配置里加上 shikiConfig

import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';

export default defineConfig({
  integrations: [mdx()],
  markdown: {
    shikiConfig: {
      theme: 'dracula', // 可选:github-dark, nord, monokai, dracula 等
    },
  },
});

Shiki 支持超多主题,我常用的有:

  • github-dark / github-light - GitHub 风格
  • dracula - 经典的紫黑配色
  • nord - 清冷的北欧风
  • one-dark-pro - VSCode 默认深色主题

你可以在 Shiki 主题预览 里挑一个自己喜欢的。

实现浅色/深色双主题切换

如果你的博客支持深浅色模式切换,Shiki 可以配置双主题:

markdown: {
  shikiConfig: {
    themes: {
      light: 'github-light',
      dark: 'github-dark',
    },
  },
},

这样配置后,Shiki 会根据 CSS 的 prefers-color-scheme 或你自定义的主题切换逻辑自动应用对应的代码高亮主题。

高亮特定行和代码注释

写教程的时候,经常需要标注”看这一行很重要”或者展示”代码改了哪些地方”。Shiki Transformers 可以实现这些功能。

高亮重点代码行

先安装 Shiki 的 transformers:

npm install shiki

然后在配置里启用 transformerNotationHighlight

import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
import { transformerNotationHighlight } from '@shikijs/transformers';

export default defineConfig({
  integrations: [mdx()],
  markdown: {
    shikiConfig: {
      theme: 'github-dark',
      transformers: [transformerNotationHighlight()],
    },
  },
});

现在可以在代码块里用 // [!code highlight] 注释来标记需要高亮的行:

```javascript
function hello() {
  console.log('这行是普通的');
  console.log('这行会高亮显示'); // [!code highlight]
}
```

展示代码变更(Diff 风格)

在对比”修改前/后”的代码时,可以用 transformerNotationDiff

import { transformerNotationDiff, transformerNotationHighlight } from '@shikijs/transformers';

markdown: {
  shikiConfig: {
    theme: 'github-dark',
    transformers: [
      transformerNotationHighlight(),
      transformerNotationDiff(),
    ],
  },
},

用法:

```javascript
function calculate(a, b) {
  return a + b; // [!code --]
  return a * b; // [!code ++]
}
```

-- 的行会显示为红色(删除),带 ++ 的行显示为绿色(新增)。这个功能写代码教程时超级实用。

聚焦特定代码

还有一个 transformerNotationFocus,可以让其他代码”变灰”,只突出你想强调的部分:

import { transformerNotationFocus } from '@shikijs/transformers';

// 添加到 transformers 数组
transformers: [
  transformerNotationFocus(),
],

使用 // [!code focus] 标记:

```javascript
function process() {
  console.log('这行会变灰');
  console.log('这行正常显示'); // [!code focus]
  console.log('这行也变灰');
}
```

升级到 Expressive Code(可选)

如果你觉得 Shiki 的功能还不够,可以试试 Expressive Code。它是社区开发的增强版代码展示方案,提供了更多开箱即用的功能:

  • 代码块标题
  • 一键复制按钮
  • 行号显示
  • 终端窗口样式
  • 代码对比(Side-by-Side)

安装超简单

npx astro add astro-expressive-code

Astro CLI 会自动配置好一切。装完后,你的代码块就自动带上这些功能了,不需要额外配置。

什么时候用 Expressive Code?

说实话,我一开始用的是默认的 Shiki,后来发现读者经常想复制代码,就换成了 Expressive Code。如果你的博客主要是写教程、分享代码,Expressive Code 能让读者体验好很多。

但如果只是偶尔放点代码,用 Shiki + Transformers 就够了,不用增加额外的依赖。

第三部分:嵌入自定义组件

在 MDX 中导入和使用组件

MDX 最强大的地方就是可以直接在文章里用组件。我经常用这个功能做提示框、代码对比、可折叠区域等。

创建一个警告框组件

先在 src/components/ 目录下创建一个 Alert.astro

---
interface Props {
  type?: 'info' | 'warning' | 'error';
}

const { type = 'info' } = Astro.props;

const styles = {
  info: 'bg-blue-50 border-blue-200 text-blue-800',
  warning: 'bg-yellow-50 border-yellow-200 text-yellow-800',
  error: 'bg-red-50 border-red-200 text-red-800',
};
---

<div class={`border-l-4 p-4 ${styles[type]}`}>
  <slot />
</div>

在 MDX 文章中使用

在你的 .mdx 文件里导入并使用它:

---
title: 我的技术文章
---

import Alert from '@/components/Alert.astro';

# 文章标题

这是普通的文章内容。

<Alert type="warning">
  注意:运行这个命令前请备份数据!
</Alert>

<Alert type="info">
  提示:你也可以在组件里用 **Markdown 语法**,很方便。
</Alert>

看到了吗?在 <Alert> 组件里,你还可以继续用 Markdown 语法(如加粗、链接等),MDX 会自动处理。

使用 React/Vue 组件

MDX 不仅支持 Astro 组件,也可以用 React、Vue 等框架组件。不过要注意加上 client: 指令:

import Counter from '@/components/Counter.tsx';

<Counter client:load initialCount={0} />

client:load 表示这个组件会在页面加载时在客户端运行。如果不加,组件只会服务端渲染,交互功能不生效。

组件文件组织建议

我习惯把文章里常用的组件放在 src/components/mdx/ 目录下,这样好管理:

src/
├── components/
│   ├── mdx/
│   │   ├── Alert.astro
│   │   ├── CodeCompare.astro
│   │   ├── Callout.astro
│   │   └── Tabs.astro
│   └── ...其他组件

映射 Markdown 语法到自定义组件

这个功能有点”黑魔法”的感觉——你可以把 Markdown 的标准元素(如 h1、a、img)替换成你自己的组件。

为什么要这么做?

比如你想给所有的标题加个锚点图标,或者给外部链接自动加个”↗“标记,手动一个个加太麻烦了。用组件映射,写标准 Markdown 就自动应用你的样式。

实战:自定义标题组件

先创建一个 CustomHeading.astro

---
interface Props {
  level: 1 | 2 | 3 | 4 | 5 | 6;
  id?: string;
}

const { level, id } = Astro.props;
const Tag = `h${level}` as any;
---

<Tag id={id} class="group relative">
  <slot />
  {id && (
    <a href={`#${id}`} class="ml-2 opacity-0 group-hover:opacity-100 transition-opacity">
      #
    </a>
  )}
</Tag>

在 MDX 中使用映射

在你的 .mdx 文件里,导出一个 components 对象:

---
title: 文章标题
---

import CustomHeading from '@/components/CustomHeading.astro';

export const components = {
  h2: (props) => <CustomHeading level={2} {...props} />,
  h3: (props) => <CustomHeading level={3} {...props} />,
};

## 这是二级标题

鼠标悬停在标题上,会出现 # 锚点链接。

### 这是三级标题

所有 h2 和 h3 都自动应用了自定义样式。

实战:给外部链接加图标

创建 ExternalLink.astro

---
interface Props {
  href?: string;
}

const { href } = Astro.props;
const isExternal = href?.startsWith('http');
---

<a href={href} target={isExternal ? '_blank' : undefined} rel={isExternal ? 'noopener noreferrer' : undefined}>
  <slot />
  {isExternal && <span class="ml-1 text-xs">↗</span>}
</a>

映射使用:

import ExternalLink from '@/components/ExternalLink.astro';

export const components = {
  a: ExternalLink,
};

[这是内部链接](/about)
[这是外部链接](https://example.com) ← 会自动加 ↗ 图标

全局配置映射(高级)

如果你想让所有 MDX 文件都用同一套组件映射,可以在 astro.config.mjs 里配置。不过这个需要自定义 MDX 插件,稍微复杂一点,我一般是在单个文件里配置就够了。

第四部分:数学公式和图表集成

集成 KaTeX 展示数学公式

如果你写算法、数学或数据科学类的文章,肯定需要展示公式。KaTeX 是目前最好的选择,比 MathJax 快很多,而且支持服务端渲染。

安装 KaTeX

需要安装三个包:

npm install remark-math rehype-katex katex
  • remark-math:解析 LaTeX 语法
  • rehype-katex:渲染公式为 HTML
  • katex:KaTeX 核心库

配置 Astro

打开 astro.config.mjs,添加这两个插件:

import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
import remarkMath from 'remark-math';
import rehypeKatex from 'rehype-katex';

export default defineConfig({
  integrations: [mdx()],
  markdown: {
    remarkPlugins: [remarkMath],
    rehypePlugins: [rehypeKatex],
  },
});

引入 KaTeX 样式

这一步很重要,不然公式渲染不出来。在你的布局文件(如 src/layouts/MarkdownLayout.astro)的 <head> 里加上:

<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.css"
  crossorigin="anonymous"
/>

在文章中使用公式

配置好后,就可以在 Markdown/MDX 里写公式了。

行内公式(用单个 $ 包裹):

质能方程:$E = mc^2$

二次方程的解:$x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}$

块级公式(用双 $$ 包裹):

$$
\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}
$$

$$
\sum_{i=1}^{n} i = \frac{n(n+1)}{2}
$$

常见问题:公式不显示

如果公式不显示或样式不对,检查这几点:

  1. KaTeX CSS 是否正确引入(F12 看 Network 面板)
  2. rehype-katex 的版本是否兼容(试试降到 6.x 版本)
  3. 公式语法是否正确(去 KaTeX 支持列表 确认)

集成 Mermaid 绘制流程图和图表

Mermaid 可以用代码画流程图、时序图、甘特图等,特别适合技术文档。

三种集成方案对比

社区有几种 Mermaid 集成方案,我简单说说区别:

方案渲染方式SEO配置难度推荐指数
rehype-mermaid服务端⭐⭐⭐⭐⭐
astro-diagram服务端⭐⭐⭐⭐
astro-mermaid客户端⭐⭐⭐

我推荐 rehype-mermaid,服务端渲染,SEO 友好,生成的是静态 SVG。

安装 rehype-mermaid

npm install rehype-mermaid

配置

astro.config.mjs 里添加:

import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
import rehypeMermaid from 'rehype-mermaid';

export default defineConfig({
  integrations: [mdx()],
  markdown: {
    rehypePlugins: [
      [rehypeMermaid, { strategy: 'img-svg' }]
    ],
  },
});

strategy: 'img-svg' 表示生成 SVG 图片,这是最稳定的方案。

在文章中画图

mermaid 代码块就行:

流程图示例

```mermaid
graph TD
    A[开始] --> B{是否安装MDX}
    B -->|是| C[配置代码高亮]
    B -->|否| D[安装MDX]
    D --> C
    C --> E[完成]
```

时序图示例

```mermaid
sequenceDiagram
    用户->>浏览器: 访问页面
    浏览器->>服务器: 请求HTML
    服务器->>浏览器: 返回渲染后的页面
    浏览器->>用户: 显示内容
```

构建时生成

运行 npm run build 时,Mermaid 图表会在构建阶段生成为 SVG,最终页面里是静态图片,加载速度快,也不需要客户端 JavaScript。

注意事项

如果构建时报错”找不到 Puppeteer”,可能需要额外配置。试试安装 playwright:

npm install -D playwright

或者换用 astro-diagram 方案,它内置了浏览器环境。

第五部分:高级技巧和最佳实践

Content Collections 的 MDX 优化

如果你用 Astro 的 Content Collections 管理博客文章(强烈推荐),MDX 文件可以获得更好的类型支持和开发体验。

Content Collections 是什么?

简单说,就是把文章放在 src/content/ 目录下,Astro 会自动识别、验证 frontmatter,并提供类型安全的 API 来读取内容。

配置 Content Collections

src/content/config.ts 定义你的集合:

import { defineCollection, z } from 'astro:content';

const blog = defineCollection({
  type: 'content', // 表示这是内容文件(Markdown/MDX)
  schema: z.object({
    title: z.string(),
    description: z.string(),
    pubDate: z.date(),
    tags: z.array(z.string()).optional(),
    draft: z.boolean().default(false),
  }),
});

export const collections = { blog };

在 MDX 中使用

MDX 文件的 frontmatter 会被自动验证:

---
title: Astro MDX 进阶教程
description: 学习 MDX 的高级用法
pubDate: 2025-12-02
tags: [Astro, MDX, 教程]
---

import Alert from '@/components/Alert.astro';

# {frontmatter.title}

<Alert type="info">
  发布日期:{frontmatter.pubDate.toLocaleDateString()}
</Alert>

自动生成目录

Content Collections 提供了 getHeadings() 方法,可以获取文章的所有标题,用来生成目录:

---
import { getEntry } from 'astro:content';

const entry = await getEntry('blog', 'my-mdx-article');
const { Content, headings } = await entry.render();
---

<aside>
  <h2>目录</h2>
  <ul>
    {headings.map(h => (
      <li style={`margin-left: ${(h.depth - 1) * 1}rem`}>
        <a href={`#${h.slug}`}>{h.text}</a>
      </li>
    ))}
  </ul>
</aside>

<article>
  <Content />
</article>

这个功能在写长文时特别实用,读者可以快速跳转到感兴趣的章节。

性能优化和常见陷阱

MDX 很强大,但用不好也会拖慢网站。这里分享几个要注意的点。

避免过度使用客户端组件

MDX 里可以用 React/Vue 组件,但别忘了加 client:* 指令。如果不加,组件只会服务端渲染,交互功能不生效;如果滥用 client:load,会增加大量 JavaScript,拖慢页面加载。

我的建议:

  • 静态内容用 Astro 组件(如 Alert、Callout)
  • 需要交互的用 client:visible(可见时才加载)或 client:idle(空闲时加载)
  • 除非必要,不用 client:load

图片优化

在 MDX 里插入图片,别直接用 <img>,用 Astro 的 Image 组件:

---
title: 我的文章
---

import { Image } from 'astro:assets';
import cover from './cover.jpg';

<Image src={cover} alt="封面图" width={800} height={600} />

Astro 会自动优化图片(压缩、生成 WebP、懒加载等),性能好很多。

MDX 的 optimize 选项

如果你的站点有很多 MDX 文件,构建很慢,可以试试开启 optimize 选项:

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

这个选项会通过内部的 rehype 插件优化 MDX 输出,加快构建速度。不过可能会改变生成的 HTML 结构,用之前先测试一下。

常见错误和解决方案

错误原因解决方案
MDX 组件不显示忘了导入组件检查 import 语句
交互组件不工作缺少 client: 指令加上 client:load
代码高亮不生效Shiki 配置错误检查 astro.config.mjs
数学公式不渲染KaTeX CSS 未引入在 layout 里加 CSS 链接
构建很慢MDX 文件太多开启 optimize 选项

结论

说了这么多,总结一下核心要点:

快速回顾 7 个技巧

  1. 配置 MDX 环境 - 一行命令搞定,5分钟上手
  2. 切换代码高亮主题 - 用 Shiki 配置你喜欢的风格
  3. 高亮和注释代码 - 用 Transformers 标注重点、展示改动
  4. 嵌入自定义组件 - 让文章更生动,从 Alert 到交互式 Demo
  5. 映射 Markdown 元素 - 批量定制标题、链接等默认样式
  6. 展示数学公式 - KaTeX 让你的算法讲解更专业
  7. 绘制流程图 - Mermaid 用代码画图,服务端渲染

学习路径建议

你不用一次性学完所有功能。我的建议是:

  • 第一步:配置好 MDX 环境,试试导入一个简单组件
  • 第二步:根据需要配置代码高亮(写代码多就配)
  • 第三步:如果写算法或架构相关,再加 KaTeX 和 Mermaid
  • 第四步:熟练后,再玩组件映射这种”黑魔法”

检查清单

配置完成后,试试这些功能是否正常:

  • MDX 文件能正常渲染
  • 代码块有正确的高亮
  • 自定义组件能显示
  • 数学公式正确渲染(如果配置了)
  • Mermaid 图表能生成(如果配置了)
  • 构建速度可接受

下一步探索

  • 浏览 Astro Integrations 找更多有意思的插件
  • 看看社区分享的 MDX 组件库
  • 试试用 Astro 的 View Transitions 给博客加上流畅的页面切换动画

现在就选一个最感兴趣的功能,在你的博客上试试吧。配置过程中遇到问题也别慌,官方文档和社区都很友好,搜一下基本都能找到答案。

话说回来,技术博客最重要的还是内容本身。这些工具只是让你的表达更清晰、更专业,真正吸引读者的,是你的观点和经验。祝你的 Astro 博客越来越好!

发布于: 2025年12月2日 · 修改于: 2025年12月4日

相关文章