关于 content-collections
content-collections 将本地 Markdown 和 MDX 文件转换为经过验证、具备类型的 TypeScript 数据,适用于内容丰富的网站。它在构建时生成可导入模块,并支持模式校验和数据转换。
主要功能
- 01解析 Markdown 和 MDX
- 02构建时校验数据模式
- 03生成带类型的 TypeScript 模块
- 04集合数据转换
- 05集成 Vite 插件
- 06支持编译 MDX
适用场景
- 01构建带类型的博客文章集合
- 02在构建时校验 frontmatter
- 03在 Vite 网站中使用本地内容
- 04在 React 中渲染 MDX 内容
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jackspace/ claudeskillz --skill content-collections安装后在 Claude Code 中输入/content-collections确认已加载。
附带文件README.mdSKILL.json
详细介绍
内容集合
状态:已可用于生产环境 ✅ 最后更新:2025-11-07 依赖项:无 最新版本:@content-collections/[email protected]、@content-collections/[email protected]、[email protected]
什么是 Content Collections?
Content Collections 会将本地内容文件(Markdown/MDX)转换为类型安全的 TypeScript 数据,并在构建时自动进行验证。
解决的问题:手动解析内容、缺少类型安全,以及无效 frontmatter 导致的运行时错误。
工作原理:
- 在
content-collections.ts中定义集合(名称、目录、Zod 架构) - CLI/插件扫描文件系统、解析 frontmatter,并根据架构进行验证
- 在
.content-collections/generated/中生成 TypeScript 模块 - 导入集合:
import { allPosts } from "content-collections"
适用于:博客、文档站点,以及使用 Cloudflare Workers、Vite、Next.js 的内容密集型应用。
快速开始(5 分钟)
1. 安装依赖项
pnpm add -D @content-collections/core @content-collections/vite zod
2. 配置 TypeScript 路径别名
添加到 tsconfig.json:
{
"compilerOptions": {
"paths": {
"content-collections": ["./.content-collections/generated"]
}
}
}
- 配置 Vite 插件
添加到 vite.config.ts:
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import contentCollections from "@content-collections/vite";
export default defineConfig({
plugins: [
react(),
contentCollections(), // MUST come after react()
],
});
4. 更新 .gitignore
.content-collections/
5. 创建集合配置
在项目根目录中创建 content-collections.ts:
import { defineCollection, defineConfig } from "@content-collections/core";
import { z } from "zod";
const posts = defineCollection({
name: "posts",
directory: "content/posts",
include: "*.md",
schema: z.object({
title: z.string(),
date: z.string(),
description: z.string(),
content: z.string(),
}),
});
export default defineConfig({
collections: [posts],
});
6. 创建内容目录
mkdir -p content/posts
创建 content/posts/first-post.md:
---
title: My First Post
date: 2025-11-07
description: Introduction to Content Collections
---
# My First Post
Content goes here...
7. 导入并使用
import { allPosts } from "content-collections";
console.log(allPosts); // Fully typed!
结果:内容具有类型安全、自动补全、验证和 HMR。
重要规则
✅ 务必执行:
- 向 tsconfig.json 添加路径别名 - 导入正常工作所必需
- 将 .content-collections 添加到 .gitignore - 生成的文件不应提交
- 使用 Standard Schema 验证器 - 支持 Zod、Valibot、ArkType
- 在架构中包含
content字段 - 解析 frontmatter 所必需 - 在转换中等待 compileMDX - MDX 编译是异步的
- 在 Vite 中将 contentCollections() 放在 react() 后面 - 插件顺序很重要
❌ 切勿执行:
- 提交 .content-collections 目录 - 此目录始终由程序生成,切勿提交
- 使用非标准验证器 - 必须支持 StandardSchema 规范
- 更改配置后忘记重启开发服务器 - 新集合生效所必需
- 在同步转换中执行异步操作 - 转换必须是异步的
- 重复包装路径别名 - 使用
content-collections,而非./content-collections - 从错误的包导入 - 配置使用
@content-collections/core,数据使用content-collections
预防已知问题
问题 #1:找不到模块:'content-collections'
错误:Cannot find module 'content-collections' or its corresponding type declarations
原因:缺少 TypeScript 路径别名配置。
预防方法:
添加到 tsconfig.json:
{
"compilerOptions": {
"paths": {
"content-collections": ["./.content-collections/generated"]
}
}
}
在 VS Code 中重启 TypeScript 服务器:Cmd+Shift+P → "TypeScript: Restart TS Server"
来源:常见用户错误
问题 #2:Vite 不断重启循环
错误:开发服务器持续重启,陷入无限循环。
原因:Vite 正在监视 .content-collections 目录的更改,从而触发重新生成。
预防方法:
- 添加到
.gitignore:
.content-collections/
- 如果问题仍然存在,添加到
vite.config.ts:
export default defineConfig({
server: {
watch: {
ignored: ["**/.content-collections/**"],
},
},
});
来源:GitHub Issue #591(TanStack Start)
问题 #3:转换后的类型未体现
错误:TypeScript 类型与转换后的文档不匹配。
原因:TypeScript 不会自动推断转换函数的返回类型。
预防方法:
为转换函数的返回值显式指定类型:
const posts = defineCollection({
name: "posts",
// ... schema
transform: (post): PostWithSlug => ({ // Type the return!
...post,
slug: post._meta.path.replace(/\.md$/, ""),
}),
});
type PostWithSlug = {
// ... schema fields
slug: string;
};
来源:GitHub Issue #396
问题 #4:文件更改后集合未更新
错误:新内容文件未出现在集合中。
原因:Glob 模式不匹配,或需要重启开发服务器。
预防方法:
- 确认 Glob 模式与文件匹配:
include: "*.md" // Only root files
include: "**/*.md" // All nested files
include: "posts/*.md" // Only posts/ folder
- 在监视范围之外添加新文件后,重启开发服务器
- 检查文件是否已保存(留意编辑器问题)
来源:常见用户错误
问题 #5:使用 Shiki 时出现 MDX 类型错误
错误:esbuild errors with shiki langAlias 或编译失败。
原因:Shiki 与 Content Collections 的版本不兼容。
预防措施:
使用兼容的版本:
{
"devDependencies": {
"@content-collections/mdx": "^0.2.2",
"shiki": "^1.0.0"
}
}
升级 Shiki 前,请查看文档中的官方兼容性矩阵。
来源:GitHub Issue #598(Next.js 15)
问题 #6:MDX 导入中的自定义路径别名失效
错误:MDX 导入中的 @ 别名无法解析。
原因:MDX 编译器不支持 tsconfig 路径别名。
预防措施:
在 MDX 导入中使用相对路径:
import Component from "@/components/Component"
import Component from "../../components/Component"
或者配置 files appender(高级用法,参见 references/transform-cookbook.md)。
来源:GitHub Issue #547
问题 #7:验证错误消息不明确
错误:晦涩的 Zod 验证错误,例如“Expected string, received undefined”。
原因:Zod 错误没有针对内容场景进行格式化。
预防措施:
为 schema 添加自定义错误消息:
schema: z.object({
title: z.string({
required_error: "Title is required in frontmatter",
invalid_type_error: "Title must be a string",
}),
date: z.string().refine(
(val) => !isNaN(Date.parse(val)),
"Date must be valid ISO date (YYYY-MM-DD)"
),
})
来源:GitHub Issue #403
问题 #8:Ctrl+C 无法停止进程
错误:开发进程退出时卡住,需要执行 kill -9。
原因:文件监视器未能正确清理。
预防措施:
这是文件监视器的已知问题。可采用以下变通方法:
- 卡住时使用
kill -9 <pid> - 单独运行
content-collections watch(而非使用插件),以便更好地控制 - 在
vite.config.ts中添加清理处理程序(高级用法)
来源:GitHub Issue #546
配置模式
基本博客集合
import { defineCollection, defineConfig } from "@content-collections/core";
import { z } from "zod";
const posts = defineCollection({
name: "posts",
directory: "content/posts",
include: "*.md",
schema: z.object({
title: z.string(),
date: z.string(),
description: z.string(),
tags: z.array(z.string()).optional(),
content: z.string(),
}),
});
export default defineConfig({
collections: [posts],
});
多集合设置
const posts = defineCollection({
name: "posts",
directory: "content/posts",
include: "*.md",
schema: z.object({
title: z.string(),
date: z.string(),
description: z.string(),
content: z.string(),
}),
});
const docs = defineCollection({
name: "docs",
directory: "content/docs",
include: "**/*.md", // Nested folders
schema: z.object({
title: z.string(),
category: z.string(),
order: z.number().optional(),
content: z.string(),
}),
});
export default defineConfig({
collections: [posts, docs],
});
转换函数(计算字段)
const posts = defineCollection({
name: "posts",
directory: "content/posts",
include: "*.md",
schema: z.object({
title: z.string(),
date: z.string(),
content: z.string(),
}),
transform: (post) => ({
...post,
slug: post._meta.path.replace(/\.md$/, ""),
readingTime: Math.ceil(post.content.split(/\s+/).length / 200),
year: new Date(post.date).getFullYear(),
}),
});
使用 React 组件的 MDX
import { compileMDX } from "@content-collections/mdx";
const posts = defineCollection({
name: "posts",
directory: "content/posts",
include: "*.mdx",
schema: z.object({
title: z.string(),
date: z.string(),
content: z.string(),
}),
transform: async (post) => {
const mdx = await compileMDX(post.content, {
syntaxHighlighter: "shiki",
shikiOptions: {
theme: "github-dark",
},
});
return {
...post,
mdx,
slug: post._meta.path.replace(/\.mdx$/, ""),
};
},
});
React 组件集成
在 React 中使用集合
import { allPosts } from "content-collections";
export function BlogList() {
return (
<ul>
{allPosts.map((post) => (
<li key={post._meta.path}>
<h2>{post.title}</h2>
<p>{post.description}</p>
<time>{post.date}</time>
</li>
))}
</ul>
);
}
渲染 MDX 内容
import { MDXContent } from "@content-collections/mdx/react";
export function BlogPost({ post }: { post: { mdx: string } }) {
return (
<article>
<MDXContent code={post.mdx} />
</article>
);
}
部署到 Cloudflare Workers
Content Collections 非常适合 Cloudflare Workers,因为它:
- 仅在构建时运行(运行时无需访问文件系统)
- 输出静态 JavaScript 模块
- 生成的代码不依赖 Node.js
部署模式
Local Dev → content-collections build → vite build → wrangler deploy
wrangler.toml
name = "my-content-site"
compatibility_date = "2025-11-07"
[assets]
directory = "./dist"
binding = "ASSETS"
构建脚本
package.json:
{
"scripts": {
"dev": "vite",
"build": "vite build",
"deploy": "pnpm build && wrangler deploy"
}
}
注意:Vite 插件会自动处理 content-collections build!
使用打包资源
模板(templates/)
可直接复制粘贴使用的配置文件:
content-collections.ts- 基本博客设置content-collections-multi.ts- 多个集合content-collections-mdx.ts- 带语法高亮的 MDXtsconfig.json- 完整的 TypeScript 配置vite.config.ts- Vite 插件设置blog-post.md- 示例内容文件BlogList.tsx- React 列表组件BlogPost.tsx- React MDX 渲染组件wrangler.toml- Cloudflare Workers 配置
参考资料(references/)
有关高级主题的深入文档:
schema-patterns.md- 常见的 Zod schema 模式transform-cookbook.md- 转换函数示例mdx-components.md- MDX + React 集成deployment-guide.md- Cloudflare Workers 设置
何时加载:需要了解基本设置之外的高级模式时,Claude 应加载这些文件。
脚本(scripts/)
init-content-collections.sh- 一键自动设置
依赖项
必需
{
"devDependencies": {
"@content-collections/core": "^0.12.0",
"@content-collections/vite": "^0.2.7",
"zod": "^3.23.8"
}
}
可选(MDX)
{
"devDependencies": {
"@content-collections/markdown": "^0.1.4",
"@content-collections/mdx": "^0.2.2",
"shiki": "^1.0.0"
}
}
官方文档
- 官方网站:https://www.content-collections.dev
- 文档:https://www.content-collections.dev/docs
- GitHub:https://github.com/sdorra/content-collections
- Vite 插件:https://www.content-collections.dev/docs/vite
- MDX 集成:https://www.content-collections.dev/docs/mdx
软件包版本(已于 2025-11-07 验证)
| 软件包 | 版本 | 状态 |
|---|---|---|
| @content-collections/core | 0.12.0 | ✅ 最新稳定版 |
| @content-collections/vite | 0.2.7 | ✅ 最新稳定版 |
| @content-collections/mdx | 0.2.2 | ✅ 最新稳定版 |
| @content-collections/markdown | 0.1.4 | ✅ 最新稳定版 |
| zod | 3.23.8 | ✅ 最新稳定版 |
故障排除
问题:TypeScript 找不到 'content-collections'
解决方案:在 tsconfig.json 中添加路径别名,然后重启 TS 服务器。
问题:Vite 不断重启
解决方案:将 .content-collections/ 添加到 .gitignore 和 Vite 的监视忽略列表中。
问题:更改未生效
解决方案:重启开发服务器,检查 glob 模式,并确认文件已保存。
问题:MDX 编译错误
解决方案:检查 Shiki 版本兼容性,并验证 MDX 语法。
问题:验证错误不明确
解决方案:为 Zod 架构添加自定义错误消息。
完整设置清单
- 已安装
@content-collections/core和@content-collections/vite - 已安装用于架构验证的
zod - 已在
tsconfig.json中添加路径别名 - 已将
contentCollections()添加到vite.config.ts(位于 react() 之后) - 已将
.content-collections/添加到.gitignore - 已在项目根目录创建
content-collections.ts - 已创建内容目录(例如
content/posts/) - 已使用 Zod 架构定义集合
- 已创建带有 frontmatter 的首个内容文件
- 已在 React 组件中导入集合
- 已验证类型正常工作(自动补全)
- 已测试热重载(更改内容文件)
有疑问?遇到问题?
- 查看
references/目录中的深入说明 - 验证 tsconfig.json 中的路径别名
- 检查 Vite 插件顺序(位于 react() 之后)
- 查看上述已知问题
- 查看官方文档:https://www.content-collections.dev/docs