TL;DR
Markdown 文件经过 frontmatter 解析 → Markdown 编译 → Astro 组件注入 → HTML 生成,最终变成读者看到页面。理解这个管线,就知道该在哪个环节解决问题。
完整管线
.md 文件
↓ 1. 读取文件
↓ 2. 解析 frontmatter
↓ 3. 交给 remark/rehype 处理
↓ 4. 生成 HTML
↓ 5. 注入 Astro 组件
↓ 6. 应用 scoped CSS
↓ 7. 输出最终 HTML
步骤详解
1. 读取文件
Astro 的 Content Collections 扫描 src/content/blog/ 目录,找到所有 .md 和 .mdx 文件。
2. 解析 frontmatter
--- 之间的 YAML 内容解析为 JavaScript 对象:
---
title: '我的文章'
pubDate: 2026-06-09
tags: ['Astro']
---
解析结果:
{
title: '我的文章',
pubDate: new Date('2026-06-11'),
tags: ['Astro']
}
这一步由 content.config.ts 中的 schema 做类型校验。字段类型不对会报构建错误。
3. remark/rehype 处理
Astro 使用 remark(Markdown 处理器)和 rehype(HTML 处理器)的管线:
Markdown → remark-parse → remark-rehype → rehype-stringify → HTML
关键插件:
remark-gfm:GitHub Flavored Markdown(表格、删除线、任务列表)rehype-pretty-code:代码高亮(基于 Shiki)@astrojs/mdx:MDX 支持(在 Markdown 中使用组件)
4. 生成 HTML
Markdown 正文编译为 HTML 字符串。
## 标题
这是**加粗**文字。
编译为:
<h2 id="标题">标题</h2>
<p>这是<strong>加粗</strong>文字。</p>
注意:标题自动生成 id 属性,用于目录(TOC)跳转。
5. 注入 Astro 组件
文章 HTML 注入到 BlogPost.astro(或你配置文章布局)中:
---
const { Content } = await entry.render();
---
<article>
<h1>{entry.data.title}</h1>
<Content /> <!-- 这里是文章 HTML -->
</article>
6. 应用 scoped CSS
Astro 给组件内所有元素添加 data-astro-cid-xxx,CSS 选择器也加上对应属性。详见 CSS scoped 编译机制。
7. 输出最终 HTML
最终输出 HTML 包含:站点布局 + 文章内容 + 组件交互 + scoped 样式。
MDX 的额外步骤
MDX 允许在 Markdown 中使用 JSX 组件:
## 正文
*Counter 组件已移除*
额外步骤:MDX 解析器需要识别 JSX 语法,将组件编译为 Astro 可执行模块。
注意事项:
- 组件导入路径必须用相对路径,不能用
@components别名 - MDX 文件的
<style is:global>会丢弃,需要用外部 CSS 文件
常见问题
代码块不显示高亮?
检查 astro.config.mjs 是否配置了代码高亮:
export default defineConfig({
markdown: {
shikiConfig: {
theme: 'github-dark',
},
},
});
或者使用 Expressive Code 替代 Shiki。
frontmatter 字段不生效?
检查 content.config.ts 的 schema 定义。新增字段必须同时在 schema 中声明。
目录(TOC)为空?
Astro 的 getHeadings() 只收集 <h2> 到 <h4>。如果文章只有 <h1> 和 <h5>,TOC 为空。
写在
理解渲染管线后,遇到问题可以快速定位是哪个环节出错:frontmatter 问题看 schema,编译问题看 remark/rehype,布局问题看 Astro 组件,样式问题看 scoped CSS。
种下你的想法
在花园里留下一条评论,和这篇文章一起生长。