返回

Astro 内容集合详解

深入理解 Astro 的 Content Collections API,如何定义 schema、查询内容、生成动态路由。

· 3 分钟阅读 技术

Astro 的 Content Collections 是管理 Markdown/MDX 内容的官方方案。这篇文章记录一下核心用法。

为什么用 Content Collections

在 Astro 2.0 之前,内容文件散落在各个目录里,靠 glob() 查询。问题很明显:

  • 没有类型安全
  • 没有数据校验
  • 没有自动补全

Content Collections 解决了这些问题。

定义 Schema

// src/content/config.ts
import { defineCollection, z } from 'astro:content';

const blog = defineCollection({
  type: 'content',
  schema: z.object({
    title: z.string(),
    description: z.string().optional(),
    pubDate: z.coerce.date(),
    category: z.enum(['tech', 'life']),
    tags: z.array(z.string()).default([]),
    featured: z.boolean().default(false),
  }),
});

export const collections = { blog };

关键点:

  • z.coerce.date() — 自动把 YAML 里的日期字符串转成 Date 对象
  • z.enum() — 限制可选值,写错会报错
  • .default() — 设置默认值,frontmatter 里不写也行

查询内容

import { getCollection } from 'astro:content';

const posts = await getCollection('blog');
const sorted = posts.sort((a, b) =>
  b.data.pubDate.valueOf() - a.data.pubDate.valueOf()
);

动态路由

export async function getStaticPaths() {
  const posts = await getCollection('blog');
  return posts.map(post => ({
    params: { slug: post.id },
    props: { post },
  }));
}

渲染内容

import { render } from 'astro:content';

const { Content } = await render(post);

Content 是一个 Astro 组件,直接在模板里用就行。

总结

Content Collections 的核心价值是类型安全 + 数据校验。对于博客这种内容驱动的站点,几乎是必选项。