首页 / Astro 教程 / Markdown 内容编写

Astro 教程

Markdown 内容编写

本教程共 56 篇 · 第 17 篇 · 更新于 2026-08-07 · 约 9 分钟阅读

AstroAstro 教程Markdownfrontmatter内容编写Astro 组件GitHub Flavored MarkdownAstro 教程入门

本节目标:搞懂在 Astro 里怎么写 Markdown 文章,以及怎么把它放进页面和组件里展示出来。

写博客、写文档,很多人第一反应就是用 Markdown。它简单,纯文本就能写,不用管排版细节。Astro 把 Markdown 当成一等公民,你写好的 .md 文件,框架能直接读、直接渲染成网页。

这一章我们从「是什么、放哪里、怎么用」三个角度,把 Markdown 在 Astro 里的基础用法讲清楚。内容集合那种更高级的玩法,留到后面两章专门说。

Markdown 到底是什么

先说人话。Markdown 是一种轻量级标记语言,用普通文本写内容,靠几个简单符号来表达格式。比如用 # 表示标题,用 ** 包住文字表示加粗。

# 这是一级标题

这是一段普通文字,下面有个 **加粗** 和一个 *斜体*

- 列表项一
- 列表项二

[点我去 Astro 官网](https://astro.build)

你看到的这些符号,最后会被转成浏览器认识的 HTML(<h1><strong> 之类)。Astro 内部用的规则叫 GitHub Flavored Markdown,也就是 GitHub 上写 issue、写 README 那套语法,比标准 Markdown 多了删除线、表格、任务清单等好用的东西。

Note

Markdown 文件本身只管「内容」。样式归样式,布局归布局,Astro 把内容渲染出来后,长什么样由你的组件和 CSS 决定。

文件该放在哪里

Astro 对 Markdown 文件的位置很宽松。放在 src/ 目录下的任何地方都行。

src/
├── pages/
│   └── about.md        ← 放在 pages 下,自动变成页面
├── posts/
│   └── hello.md        ← 放在别处,需要手动导入使用
└── components/

有个关键区别要记牢:放在 src/pages/ 里的 .md 文件,Astro 会自动帮你生成一个网页。文件叫 about.md,访问地址就是 /about/。这跟 .astro 页面文件的规则一模一样。

不放在 pages/ 里的 Markdown,Astro 不会自动给它建页面。你得在组件里用「导入」的方式把它读进来,再决定怎么展示。适合你有一堆文章、想集中管理又想自己控制排版的场景。

Tip

文章数量多、结构统一(比如都是博客帖子),更推荐用「内容集合」来管。那是第 20、21 章的主角。本章先把最朴素的文件用法讲明白。

frontmatter 是什么

Markdown 文件顶部那一小段用 --- 包起来的内容,叫 frontmatter(这个词不翻译,直接这么叫)。它用的是 YAML 格式,用来给文章定义一些「属性」,比如标题、作者、描述。

---
title: 我的第一篇 Astro 文章
author: 码上学
description: 记录我第一次用 Astro 写东西
---

正文从这里开始写……

这些属性不会显示成正文,但它们会变成「数据」,可以在代码里拿到。比如你想在列表页展示每篇文章的标题,靠的就是 frontmatter 里的 title

Astro 还认 TOML 格式的 frontmatter,不过日常几乎都写 YAML,因为它最直观。

在组件里导入 Markdown

想在一篇 .astro 组件里用另一个 Markdown 文件,最直接的方式是 import

---
// 导入单个 Markdown 文件
import * as greatPost from "../posts/great-post.md";

// 也可以用 import.meta.glob 一次性导入多个
const posts = Object.values(import.meta.glob("../posts/*.md", { eager: true }));
---

<p>{greatPost.frontmatter.title}</p>
<p>作者:{greatPost.frontmatter.author}</p>

<ul>
  {posts.map((post) => (
    <li><a href={post.url}>{post.frontmatter.title}</a></li>
  ))}
</ul>

import.meta.glob 是 Vite 提供的能力,能按路径规则匹配一批文件。上面那段就是「把 posts 目录下所有 .md 抓进来,列成一个链接清单」。

导入之后,你能拿到下面这些属性:

  • file:文件的绝对路径。
  • url:这个文件对应的网页地址。
  • frontmatter:你在 --- 里写的那些属性。
  • <Content />:一个组件,渲染整篇 Markdown 的正文。
  • rawContent():返回原始 Markdown 文本的函数。
  • compiledContent():返回编译后 HTML 字符串的异步函数。
  • getHeadings():返回所有标题信息的异步函数。

<Content /> 渲染正文

最常用的就是 <Content />。它把 Markdown 正文原原本本渲染成 HTML 塞进页面。

---
import { Content as PromoBanner } from '../components/promoBanner.md';
---

<h2>今日推荐</h2>
<PromoBanner />

上面把导入的 Content 改名叫 PromoBanner,效果一样,只是名字更顺眼。组件名你随便起,它干的活都是「把那篇 Markdown 画出来」。

如果你想拿到编译好的 HTML 字符串自己处理,用 compiledContent()

---
import * as post from "../posts/great-post.md";
const html = await post.compiledContent();
---

<Fragment set:html={html} />

set:html 是把字符串当 HTML 直接注入。这种写法少用,大多数情况 <Content /> 就够了。

标题自动带锚点

你可能见过这种链接:点一下就能跳到页面某个小节。Astro 给 Markdown 里的每个标题(h1h6)自动加上 id,所以锚点链接天然就好用。

## 引言

我可以链接到同页的 [结论](#结论) 一节。

## 结论

浏览器打开 `页面地址/#引言` 就能直接定位到「引言」。

这些 id 是用 github-slugger 这个工具生成的,规则跟 GitHub 标题锚点一致:中文会保留,空格变成短横线。

想拿到所有标题的清单(比如做目录),用 getHeadings()。它返回这样的数组:

[
  { depth: 1, slug: "astro-018-release", text: "Astro 0.18 Release" },
  { depth: 2, slug: "responsive-partial-hydration", text: "Responsive partial hydration" }
]

slug 就是标题的 iddepth 是几级标题,text 是标题文字。

单独 Markdown 页面加外壳

直接丢在 src/pages/ 里的 .md 文件,Astro 会渲染,但默认没有你网站的导航、页脚等「外壳」。给它套个布局,靠 frontmatter 里的 layout 属性。

---
layout: ../../layouts/BlogPostLayout.astro
title: Astro 简介
author: 码上学
description: 看看 Astro 厉害在哪
---

这是用 Markdown 写的一篇帖子。

layout 的值是一个相对路径,指向一个 Astro 布局组件。这个布局组件里,你能通过 Astro.props.frontmatter 拿到上面那些属性:

---
const { frontmatter } = Astro.props;
---

<html>
  <head><meta charset="utf-8"></head>
  <body>
    <h1>{frontmatter.title}</h1>
    <h2>作者:{frontmatter.author}</h2>
    <slot />  <!-- Markdown 正文注入到这里 -->
  </body>
</html>
Note

用了 layout 之后,<meta charset="utf-8"> 得自己在布局里写,Astro 不再自动加。不写的话,中文可能会乱码。

slot 是 Astro 里的「插槽」概念,简单理解就是「内容塞进来的位置」。Markdown 正文就从这进来。

Markdown 处理器能换

Astro 把 Markdown 转成 HTML,靠的是一个叫「Markdown 处理器」的东西。默认用的是 Sätteri,这是 Astro 自家带的引擎,开箱即用,不用额外装。

如果你习惯了 remark / rehype 那套生态(一堆社区插件),可以在配置里换成 unified()

// astro.config.mjs
import { defineConfig } from 'astro/config';
import { unified } from '@astrojs/markdown-remark';

export default defineConfig({
  markdown: {
    processor: unified(),
  },
});

换处理器之前要先装 @astrojs/markdown-remark。一般新手用默认的 Sätteri 就行,遇到特殊需求再考虑切换。

小结

这一章讲的是 Markdown 在 Astro 里的基础用法。记住几件事:放在 src/pages/ 自动成页;frontmatter 给文章存属性;组件里用 importimport.meta.glob 导入;<Content /> 负责渲染;标题自动带锚点;单独页面用 layout 套外壳。

内容少的时候这么玩挺顺手。等你文章变多、想要类型检查、想要集中查询,就该上「内容集合」了。下一章先讲 MDX,再往后两章就是内容集合的重头戏。