Astro 内容集合
内容集合解决什么问题
当文章变多,用 src/pages/ 直接放 Markdown 会遇到几个麻烦:每篇都要手写 front-matter、字段容易写错、难以统一校验。
内容集合(Content Collections)用一份 schema 集中定义规则,所有文章自动受约束。
定义集合
在 Astro 7 中,集合配置放在 src/content.config.ts。
// src/content.config.ts
import { defineCollection, z } from 'astro:content';
import { glob } from 'astro/loaders';
const blog = defineCollection({
loader: glob({ pattern: '**/*.md', base: './src/content/blog' }), // glob 加载指定目录下的所有 .md 文件
schema: z.object({
title: z.string(),
date: z.coerce.date(), // z 是 Zod 校验库,这里把字符串强制转成 Date
tags: z.array(z.string()).default([]),
}),
});
export const collections = { blog };
这里做了三件事:
- 用
glob加载src/content/blog下的所有.md。 - 用
z.object(Zod 是一个 schema 校验库)定义每篇文章必须有什么字段。 - 导出
collections,供后续查询使用。
文章文件
在 src/content/blog/ 下放 Markdown,front-matter 须符合 schema。
---
title: 我的第一篇文章
date: 2026-08-26
tags: [astro, 入门]
---
这里是正文内容。
一旦某个字段缺失或类型不对,构建时就会报错,避免低级问题流到线上。
查询集合
在页面或组件里用 getCollection 读取。
---
import { getCollection } from 'astro:content';
const posts = await getCollection('blog'); // 读取 blog 内容集合,得到文章数组
---
<ul>
{posts.map((post) => (
<li><a href={`/blog/${post.id}`}>{post.data.title}</a></li>
))}
</ul>
注意文章正文通过 post.data 访问,post.id 是文件名(不含扩展名)。
渲染条目正文
拿到条目后,如果想把 Markdown 正文渲染成页面,可以调用条目的 render() 方法,它返回一个含 Content 组件的对象(还有 headings 等)。Content 就是渲染好的正文,直接当组件用即可。
---
import { getCollection } from 'astro:content';
const posts = await getCollection('blog');
const post = posts[0];
const { Content } = await post.render(); // render() 返回 { Content } 组件,用来渲染 Markdown 正文
---
<article>
<h1>{post.data.title}</h1>
<Content /> <!-- 把 Markdown 正文渲染成 HTML 插入这里 -->
</article>
补充一点:astro:content 是 Astro 在构建时自动生成的模块,里面提供了 defineCollection、getCollection 等内容集合相关的函数与类型,所以上面才能直接从它导入。
加筛选条件
getCollection 第二个参数可以过滤。
const featured = await getCollection('blog', ({ data }) => data.tags.includes('astro'));
排序
拿到数组后按字段排序。
posts.sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf());
小结
- 内容集合用 schema 统一管理文章字段。
- Astro 7 用
globloader +src/content.config.ts定义。 getCollection读取,post.data取字段,post.id取路径。- 条目用
render()得到<Content />组件,渲染 Markdown 正文。 - 字段写错会在构建时报错,保障质量。