- 起步
- 核心概念
- 教程
- 基础内容
- 内置功能
- 集成
- 操作指南
- 使用指南
- 配置
- 参考
- 社区资源
- 其他
- 为文档做出贡献
- 手动安装 Astro
- 升级到 Astro v4
- 升级到 Astro v3
- 升级到 Astro v2
- Legacy v0.x Upgrade Guide
- 从 Create React App(CRA)迁移
- 关于本教程
- 第一单元:前期准备
- 准备开发环境
- 创建你的第一个 Astro 项目
- 你的第一行 Astro 代码
- 创建在线代码仓库
- 将你的网站部署到网络
- 第二单元:页面
- 创建你的第一个 Astro 页面
- 编写你的第一篇 Markdown 博客文章
- 添加「关于你」的动态内容
- 给你的「关于」页面添加样式
- 应用全局样式
- 第三单元:组件
- 创建一个可重复使用的导航组件
- 创建社交媒体 footer
- 自己动手搭建导航 Header
- 编写你的第一个浏览器脚本
- 第四单元:布局
- 编写你的第一个布局
- 创建并传递数据到博客布局
- 布局结合,两全其美
- 第五单元 - Astro API
- 创建文章存档页
- 生成标签页面
- 编写标签索引页面
- 添加 RSS 订阅源
- 第六单元 - Astro 群岛
- 搭建你的第一个 Astro 岛屿
- 回到干燥的陆地。让你的博客从白天到黑夜,无需岛屿!
- 恭喜你!
- @astrojs/mdx
- 添加阅读时间
- 创建开发者工具栏应用
- @astrojs/alpinejs
- @astrojs/lit
- @astrojs/preact
- @astrojs/react
- @astrojs/solid-js
- @astrojs/svelte
- @astrojs/vue
- @astrojs/cloudflare
- @astrojs/netlify
- @astrojs/node
- @astrojs/vercel
- @astrojs/db
- @astrojs/markdoc
- @astrojs/partytown
- @astrojs/sitemap
- @astrojs/tailwind
- 使用流式处理来提升页面性能
- 从 Gatsby 迁移
- 从 Next.js 迁移
- 从 NuxtJS 迁移
- 从 Docusaurus 迁移到 Astro
- 从 Eleventy 迁移到 Astro
- 从 GitBook 迁移到 Astro
- 从Gridsome迁移到Astro
- 从 Hugo 迁移
- 从 Jekyll 迁移
- 从 Pelican 迁移
- 从 SvelteKit 迁移
- 从VuePress迁移
- 从 WordPress 迁移
- 状态共享
- Storyblok 与 Astro
- Contentful 与 Astro
- ButterCMS & Astro
- Builder.io & Astro
- Cosmic 与 Astro
- DatoCMS 与 Astro
- Front Matter CMS 与 Astro
- Ghost & Astro
- Hashnode & Astro
- Hygraph 与 Astro
- Keystatic & Astro
- Kontent.ai 与 Astro
- 无头模式的 Statamic 与 Astro
- Strapi 与 Astro
- Tina CMS 与 Astro
- Umbraco & Astro
- 无头(headless)模式的 WordPress 与 Astro
- ApostropheCMS 与 Astro
- Caisy & Astro
- CloudCannon与Astro
- Crystallize 与 Astro
- Decap CMS 与 Astro
- Directus 与 Astro
- KeystoneJS 与 Astro
- microCMS & Astro
- Payload CMS 与 Astro
- Prepr CMS & Astro
- Prismic & Astro
- Sanity & Astro
- Sitecore 体验管理器 & Astro
- Spinal & Astro
- 创作内容
- Firebase 与 Astro
- Supabase 与 Astro
- Turso 和 Astro
- Xata 与 Astro
- Appwrite & Astro
- 部署你的 Astro 站点至 Netlify
- 部署你的 Astro 站点至 Vercel
- 如何将你的 Astro 网站部署到 Deno
- 部署你的 Astro 站点至 GitHub Pages
- 部署你的 Astro 站点至 GitLab Pages
- 部署你的 Astro 站点至 Cloudflare Pages
- 将你的 Astro 网站部署到 AWS
- 将你的 Astro 网站通过 Flightcontrol 部署到 AWS
- 将你的 Astro 网站通过 SST 部署到 AWS
- 将你的 Astro 网站部署至 Google Cloud
- 部署你的 Astro 站点至 Google Firebase 托管
- 将你的 Astro 网站部署到 Heroku
- 将你的 Astro 网站部署到 Microsoft Azure
- 部署你的 Astro 站点至 Buddy
- 将你的 Astro 网站部署到 Edgio
- 将你的 Astro 站点部署到 Fly.io
- 将你的 Astro 网站部署到 Render
- 将你的 Astro 网站部署到 Stormkit
- 将你的 Astro 网站部署到 Surge
- 通过 Cleavr 部署你的 Astro 网站
- 将你的 Astro 站点部署到 Kinsta 应用托管
- 将你的 Astro 网站部署到 Space
- 将你的 Astro 站点部署到 Zeabur
- 将你的 Astro 网站部署到 Zerops
- 添加 RSS 摘要
- 安装一个 Vite 或 Rollup 插件
- 构建自定义图像组件
- 使用 API 路由构建表单
- 在 Astro 页面中构建 HTML 表单
- 在 Astro 中使用 Bun
- 调用服务器端点
- 校验验证码
- 用 Docker 来构建你的 Astro 网站
- 动态导入图片
- 为链接添加图标
- 添加 i18n 功能
- 添加最后修改时间
- 在 Astro 组件中共享状态
- 使用 Tailwind Typography 美化渲染后的 Markdown
- Unknown compiler error.
- Astro.redirect is not available in static mode.
- Astro.clientAddress is not available in current adapter.
- Astro.clientAddress cannot be used inside prerendered routes.
- Astro.clientAddress is not available in static mode.
- No static path found for requested path.
- Invalid type returned by Astro page.
- Missing value for client:media directive.
- No matching renderer found.
- No client entrypoint specified in renderer.
- Missing hint on client:only directive.
- Invalid value returned by a getStaticPaths path.
- Invalid entry inside getStaticPath's return value
- Invalid value returned by getStaticPaths.
- getStaticPaths RSS helper is not available anymore.
- Missing params property on getStaticPaths route.
- Invalid value for getStaticPaths route parameter.
- getStaticPaths() function required for dynamic routes.
- Invalid slot name.
- Cannot use Server-side Rendering without an adapter.
- No import found for component.
- Invalid prerender export.
- Invalid component arguments.
- Page number param not found.
- Image missing required "alt" property.
- Error while loading image service.
- Missing image dimensions
- Failed to retrieve remote image dimensions
- Unsupported image format
- Unsupported image conversion
- Prerendered dynamic endpoint has path collision.
- Expected src to be an image.
- Expected image options.
- Cannot set both densities and widths
- Image not found.
- Could not process image metadata.
- Image not found.
- Could not transform image.
- Unable to set response.
- The middleware didn't return a Response.
- The middleware returned something that is not a Response object.
- The endpoint did not return a Response.
- Value assigned to locals is not accepted.
- Astro.response.headers must not be reassigned.
- Can't load the middleware.
- Local images must be imported.
- Astro.glob() used outside of an Astro file.
- Astro.glob() did not match any files.
- A redirect must be given a location with the Location header.
- Invalid dynamic route.
- Could not find Sharp.
- Unknown Vite Error.
- Could not import file.
- Invalid glob pattern.
- Astro couldn't find the correct page to render
- The provided locale does not exist.
- Index page not found.
- You can't use the current function with the current strategy
- Prerendered routes aren't supported when internationalization domains are enabled.
- 启用了手动国际化路由但没有提供中间件。
- Astro can't render the route.
- Unhandled rejection
- i18n Not Enabled
- Route not found.
- Unknown CSS Error
- CSS Syntax Error
- Unknown Markdown Error.
- Failed to parse Markdown frontmatter.
- Invalid frontmatter injection.
- MDX integration missing.
- Unknown configuration error.
- Specified configuration file not found.
- Legacy configuration detected.
- Unknown CLI Error.
- Failed to generate content types.
- Unknown Content Collection Error.
- Content entry frontmatter does not match schema.
- Invalid content entry slug.
- Content Schema should not contain slug.
- Collection does not exist
- Content and data cannot be in same collection.
- Collection contains entries of a different type.
- Data collection entry failed to parse.
- Duplicate content entry slug.
- Actions must be used with server output.
- Unsupported transform in content config.
内容集合
添加于: astro@2.0.0
在任何 Astro 项目中,内容集合是使用 Markdown 和 MDX 的最佳方式。内容集合帮助管理你的文档,校验 frontmatter,并为所有内容提供自动 TypeScript 类型安全。
什么是内容集合?
一个内容集合是保留在 src/content
目录中的任何顶级目录,比如 src/content/newsletter
和 src/content/authors
。内容集合只允许在 src/content
目录中。此目录不能用于其他用处。
一个内容条目是存储在内容集合目录中的任何内容片段。内容条目存储在 Markdown (.md
) 或 MDX (.mdx
) 文件中。你可以使用任何想用的文件名,但是我们建议使用一致的命名方案 (小写,破折号而不是空格) ,以便更容易地查找和组织内容。条目可以使用内容文件的格式,包括 Markdown (.md
) 和 MDX (.mdx
使用 MDX 集成) 或者被支持的二者之一的数据格式:YAML (.yaml
) 和 JSON (.json
)。我们建议为文件使用一致的命名方案(小写、破折号而不是空格),以便更轻松地查找和组织你的内容,但这不是必须的。你还可以通过在文件名前添加下划线 (_) 来从构建中排除条目。
文件夹src/content/
文件夹newsletter/ “newsletter” 集合
- week-1.md 一个集合条目
- week-2.md 一个集合条目
- week-3.md 一个集合条目
一旦有了一个集合,你就可以使用 Astro 的内置内容 API 开始查询集合。
“.astro” 目录
Astro 将内容集合的重要元数据存储在项目中的 .astro
目录。你不需要采取任何措施来维护或更新此目录。我们希望你在项目中完全忽略它。
只要运行astro dev
,astro build
命令,.astro
目录就会自动更新。你可以随时运行astro sync
来手动更新 .astro
目录。
组织多个集合
如果两个文件表示不同类型的内容(例如,一篇博客文章和一个作者描述文件),那么它们很可能应属于不同的集合。这一点非常重要,因为许多特性(frontmatter 验证、自动 TypeScript 类型安全)要求集合中的所有条目共享相似的结构。
如果你发现自己正在处理不同类型的内容,则应该创建多个集合来表示每种类型。你可以在项目中创建任意多个不同的集合。
文件夹src/content/
文件夹newsletter/
- week-1.md
- week-2.md
文件夹blog/
- post-1.md
- post-2.md
文件夹authors/
- grace-hopper.json
- alan-turing.json
使用子目录进行组织
内容集合始终是 src/content/
目录中的顶级文件夹。你不能将一个集合嵌套在另一个集合中。不过,你可以使用子目录来组织集合中的内容。
例如,可以使用以下目录结构在单个 docs
集合中组织 i18n 翻译。当查询这个集合时,你将能够使用文件路径按语言过滤结果。
文件夹src/content/
文件夹docs/ 此集合使用子目录按语言进行组织
文件夹en/
- …
文件夹es/
- …
文件夹de/
- …
定义集合
要充分利用内容集合,请在项目中创建一个 src/content/config.ts
文件(也支持 .js
和 .mjs
)。这是一个特殊的文件,Astro 将自动加载并使用它来配置你的内容集合。
// 1. 从 `astro:content` 导入
import { defineCollection } from 'astro:content';
// 2. 定义集合
const blogCollection = defineCollection({ /* ... */ });
// 3. 导出一个 `collections` 对象来注册集合
// 这个键应该与 `src/content` 中的集合目录名匹配
export const collections = {
'blog': blogCollection,
};
设置 TypeScript
如果你没有已经在 tsconfig.json
文件中扩展 Astro 推荐的 strict
或 strictest
的 TypeScript 设置,你可能需要更新 tsconfig.json
来启用 strictNullChecks
。
{
// 注意:如果使用 `astro/tsconfigs/strict` 或 `astro/tsconfigs/strictest`,则不需要更改
"extends": "astro/tsconfigs/base",
"compilerOptions": { "strictNullChecks": true
}
}
如果在 Astro 项目中使用 .js
或者 .mjs
文件,你可以启用 IntelliSense,并在编辑器中通过在 tsconfig.json
中启用 allowJs
来进行类型检查:
{
// 注意:如果使用 `astro/tsconfigs/strict` 或 `astro/tsconfigs/strictest`,则不需要更改
"extends": "astro/tsconfigs/base",
"compilerOptions": {
"strictNullChecks": true, "allowJs": true
}
}
定义集合模式
schema 在集合中强制执行一致的 frontmatter。schema 保证当你需要引用或查询它时,你的 frontmatter 以可预测的形式存在。如果任何文件违反了它的集合 schema,Astro 将提供一个有用的错误让你知道。
schema 还使 Astro 能为内容自动生成 TypeScript 类型。为集合定义 schema 时,Astro 将自动生成并向其应用 TypeScript 接口。查询集合时,结果是完全支持 TypeScript,包括属性自动完成和类型检查。
要定义你的第一个内容 schema,如果该文件不存在的话,新建一个 src/content/config.ts
文件(.js
和 .mjs
后缀也是支持的)。此文件应该:
- 从
astro:content
导入适当的工具。 - 定义要验证的每个集合。这包括一个
type
(Astro v2.5.0 中引入) 指定集合是否包含像 Markdown (type: 'content'
) 的内容创作格式或是像 JSON 及 YAML (type: 'data'
) 的数据格式。同样包含一个用来定义 frontmatter 形式或条目数据的schema
。 - 导出一个
collections
对象来注册你的集合。
// 1. 从 `astro:content` 导入适当的工具。
import { z, defineCollection } from 'astro:content';
// 2. 定义要用 schema 验证的每个集合。
const blogCollection = defineCollection({
type: 'content', // v2.5.0 及之后
schema: z.object({
title: z.string(),
tags: z.array(z.string()),
image: z.string().optional(),
}),
});
// 3. 导出一个 `collections` 对象来注册你的集合。
export const collections = {
'blog': blogCollection,
};
定义多个集合
你可以多次使用 defineCollection()
创建多个 schema。所有集合必须从这个 collections
对象中导出。
const blogCollection = defineCollection({
type: 'content',
schema: z.object({ /* ... */ })
});
const newsletter = defineCollection({
type: 'content',
schema: z.object({ /* ... */ })
});
const authors = defineCollection({
type: 'data',
schema: z.object({ /* ... */ })
});
export const collections = {
'blog': blogCollection,
'newsletter': newsletter,
'authors': authors,
};
随着项目的增长,你还可以自由地重新组织代码库,并将逻辑移出 src/content/config.ts
文件。分别定义 schema 对于跨多个集合重用 schema 和与项目的其他部分共享 schema 非常有用。
// 1. 导入你的实用工具和 schema
import { defineCollection } from 'astro:content';
import { blogSchema, authorSchema } from '../schemas';
// 2. 定义你的集合
const blogCollection = defineCollection({
type: 'content',
schema: blogSchema,
});
const authorCollection = defineCollection({
type: 'data',
schema: authorSchema,
});
// 3. 导出多个集合以注册它们
export const collections = {
'blog': blogCollection,
'authors': authorCollection,
};
使用第三方集合 schema
你可以从任何地方导入集合 schema,包括外部 npm 包。这在使用提供了它们自己的集合 schema 的主题和库时非常有用。
src/content/config.tsimport { blogSchema } from 'my-blog-theme';
const blogCollection = defineCollection({ type: 'content', schema: blogSchema });
// 导出从 'my-blog-theme' 导入的 schema 为 `blog` 集合
export const collections = {
'blog': blogCollection,
};
用 Zod 定义数据类型
Astro 使用 Zod 驱动其内容 schema。Astro 使用 Zod 能够验证集合中每个文件的 frontmatter,并在从项目内部查询内容时提供自动的 TypeScript 类型。
要在 Astro 中使用 Zod,请从 "astro:content"
中导入 z
。这是 Zod 库的重新导出,它支持 Zod 的所有特性。查看Zod 的 README 获得关于 Zod 如何工作以及可用特性的完整文档。
// 例子:许多常见 Zod 数据类型的备忘单
import { z, defineCollection } from 'astro:content';
defineCollection({
schema: z.object({
isDraft: z.boolean(),
title: z.string(),
sortOrder: z.number(),
image: z.object({
src: z.string(),
alt: z.string(),
}),
author: z.string().default('Anonymous'),
language: z.enum(['en', 'es']),
tags: z.array(z.string()),
// 一个可选的 frontmatter 属性。非常普遍!
footnote: z.string().optional(),
// 在 frontmatter 中,周围没有引号的日期被解释为 Date 对象
publishDate: z.date(),
// 可以将日期字符串 (例如 "2022-07-08") 转换为 Date 对象
// publishDate: z.string().transform((str) => new Date(str)),
//Advanced: 验证字符串是否也是电子邮件
authorContact: z.string().email(),
// Advanced: 验证该字符串也是一个 URL
canonicalURL: z.string().url(),
})
})
定义集合引用
集合条目也可以”引用”其他相关条目。
使用集合 API 中的 reference()
函数,可以将集合 schema 中的属性定义为另一个集合中的条目。例如,你可以要求每个 space-shuttle
条目都包含一个 pilot
属性,该属性使用 pilot
集合自己的 schema 进行类型检查、自动填充和验证。
一个常见的示例是引用以 JSON 形式存储的可重用作者个人资料或存储在同一集合中的相关帖子 URL 的博客文章:
import { defineCollection, reference, z } from 'astro:content';
const blog = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
// 通过 `id` 引用 `authors` 集合中的单个作者
author: reference('authors'),
// 通过 `slug` 引用 `blog` 集合中的相关帖子数组
relatedPosts: z.array(reference('blog')),
})
});
const authors = defineCollection({
type: 'data',
schema: z.object({
name: z.string(),
portfolio: z.string().url(),
})
});
export const collections = { blog, authors };
此示例博客文章指定相关帖子的 slug
和帖子作者的 id
:
---
title: "Welcome to my blog"
author: ben-holmes # 引用 `src/content/authors/ben-holmes.json`
relatedPosts:
- about-me # 引用 `src/content/blog/about-me.md`
- my-year-in-review # 引用 `src/content/blog/my-year-in-review.md`
---
定义自定义 slugs
当使用 type: 'content'
时,每个内容条目从它的文件 id
生成一个 URL 友好的 slug
属性。slug 用于直接从集合中查询条目。在根据内容创建新页面和 URL 时,它也很有用。
你可以通过将自己的 slug
属性添加到文件 frontmatter 来覆盖条目生成的 slug。这类似于其他 Web 框架的 “permalink” 特性。"slug"
是一个特殊的保留属性名称,不允许出现在自定义集合 schema
中,也不会出现在条目的 data
属性中。
---
title: 我的博客文章slug: my-custom-slug/supports/slashes
---
你的博客文章内容在这里。
查询集合
Astro 提供了两个函数来查询一个集合并返回一个(或多个)内容条目:getCollection()
和 getEntry()
。
import { getCollection, getEntry } from 'astro:content';
// 获取集合中的所有条目。
// 需要集合的名称作为参数。
// 示例:检索 `src/content/blog/**`
const allBlogPosts = await getCollection('blog');
// 从集合中获取单个条目。
// 需要集合的名称以及
// 条目 `slug`(内容集合)或 `id`(数据集合)
// 示例:检索 `src/content/authors/grace-hopper.json`
const graceHopperProfile = await getEntry('authors', 'grace-hopper');
这两个函数都返回由 CollectionEntry
类型定义的内容条目。
使用引用的数据
首次查询集合条目后,必须再单独查询 schema 中定义的引用。你可以再次使用 getEntry()
函数或 getEntries()
从返回的 data
对象中检索引用的条目。
---
import { getEntry, getEntries } from 'astro:content';
const blogPost = await getEntry('blog', 'welcome');
// 检索单一引用
const author = await getEntry(blogPost.data.author);
// 检索引用数组
const relatedPosts = await getEntries(blogPost.data.relatedPosts);
---
<h1>{blogPost.data.title}</h1>
<p>作者:{author.data.name}</p>
<!-- ... -->
<h2>你可能也喜欢:</h2>
{relatedPosts.map(p => (
<a href={p.slug}>{p.data.title}</a>
))}
筛选集合查询
getCollection()
接受一个可选的 “filter” 回调,它允许你基于条目的 id
、slug
或 data
(frontmatter) 属性对查询进行过滤。对于 type: content
的集合,你也可以通过 slug
来过滤。
你可以使用它根据你喜欢的任何内容条件进行筛选。例如,你可以通过前端属性(如 draft
)进行过滤,以防止任何博客文章草稿发布到你的博客上:
// 例子:使用 `draft: true` 过滤内容条目
import { getCollection } from 'astro:content';
const draftBlogEntries = await getCollection('blog', ({ data }) => {
return data.draft !== true;
});
你还可以创建草稿页面,这些页面在运行开发服务器时可用,但在生产中不会构建:
// 示例:仅当构建生产时,才过滤掉具有 `draft: true` 的内容条目
import { getCollection } from 'astro:content';
const blogEntries = await getCollection('blog', ({ data }) => {
return import.meta.env.PROD ? data.draft !== true : true;
});
filter 参数还支持按集合中的嵌套目录进行筛选。由于 id
包含完整的嵌套路径,因此可以根据每个 id
的开头进行筛选,只返回特定嵌套目录中的项目:
// 例子:按集合中的子目录筛选条目
import { getCollection } from 'astro:content';
const englishDocsEntries = await getCollection('docs', ({ id }) => {
return id.startsWith('en/');
});
使用 Astro 模板中的内容
查询完集合条目后,可以直接在 Astro 组件模板内访问每个条目。这使你可以呈现诸如内容链接(使用内容 slug
)或关于内容的信息(使用 data
属性)之类的 HTML。
有关将内容呈现为 HTML 的信息,请参见下面的将内容渲染成 HTML。
src/pages/index.astro---
import { getCollection } from 'astro:content';
const blogEntries = await getCollection('blog');
---
<ul>
{blogEntries.map(blogPostEntry => (
<li>
<a href={`/my-blog-url/${blogPostEntry.slug}`}>{blogPostEntry.data.title}</a>
<time datetime={blogPostEntry.data.publishedDate.toISOString()}>
{blogPostEntry.data.publishedDate.toDateString()}
</time>
</li>
))}
</ul>
将内容作为属性传递
组件还可以将整个内容条目作为属性传递。
如果这样做,你可以使用 CollectionEntry
实用工具使用 TypeScript 正确地输入组件属性。此实用工具接受与集合 schema 名称匹配的字符串参数,并将继承该集合 schema 的所有属性。
---
import type { CollectionEntry } from 'astro:content';
interface Props {
post: CollectionEntry<'blog'>;
}
// `post` 将匹配 `blog` 集合 schema 类型
const { post } = Astro.props;
---
将内容渲染成 HTML
一旦查询,你可以使用 render()
函数属性将集合条目渲染为 HTML。调用此函数可以访问渲染的内容和元数据,包括 <Content/>
组件和所有呈现标题的列表。
---
import { getEntry } from 'astro:content';
const entry = await getEntry('blog', 'post-1');const { Content, headings } = await entry.render();
---
<p>发布于:{entry.data.published.toDateString()}</p>
<Content />
从内容生成路由
内容集合存储在 src/pages/
目录之外。这意味着默认情况下不为集合项生成路由。你将需要手动创建一个新的动态路由,以便从集合条目生成 HTML 页面。动态路由将映射传入的请求参数(例如:在 src/pages/blog/[...slug].astro
中的 Astro.params.slug
)获取集合中的正确条目。
生成路由的确切方法将取决于你的构建 output
模式:static
(默认值) 或 server
(针对 SSR)。
构建为静态输出(默认)
如果你正在构建一个静态网站(Astro 的默认行为),你可以使用 getStaticPaths()
函数在构建过程中从一个 src/pages/
组件创建多个页面。
在 getStaticPaths()
中调用 getCollection()
来查询你的内容或数据集合。然后,使用每个内容条目的 slug
属性(内容集合)或 id
属性(数据集合)创建你的新 URL 路径。
---
import { getCollection } from 'astro:content';
// 1. 为每个集合条目生成一个新路径
export async function getStaticPaths() {
const blogEntries = await getCollection('blog');
return blogEntries.map(entry => ({
params: { slug: entry.slug }, props: { entry },
}));
}
// 2. 当渲染的时候,你可以直接从属性中得到条目
const { entry } = Astro.props;
const { Content } = await entry.render();
---
<h1>{entry.data.title}</h1>
<Content />
这将为 blog
集合中的每个条目生成一个新页面。例如,src/content/blog/hello-world.md
上的条目将有一个 hello-world
的 slug,因此它的最终 URL 将是 post/hello-world/
。
构建为服务器输出(SSR)
如果你正在构建一个动态网站(使用 Astro 的 SSR 支持),则不需要在构建期间提前生成任何路径。相反,你的页面应该检查请求(使用 Astro.request
或 Astro.params
)以按需找到 slug
,然后使用 getEntry()
获取它。
---
import { getEntry } from 'astro:content';
// 1. 从传入的服务器请求中获取 slug
const { slug } = Astro.params;
if (slug === undefined) {
throw new Error("Slug is required");
}
// 2. 直接使用请求 slug 查询条目
const entry = await getEntry('blog', slug);
// 3. 如果条目不存在,则重定向到 404
if (entry === undefined) {
return Astro.redirect("/404");
}
// 4. (可选)在模板中将条目呈现为 HTML
const { Content } = await entry.render();
---
从基于文件的路由迁移
如果你已经有了一个现成的 Astro 项目,比如一个博客,它使用 Markdown 或 MDX 文件在 src/pages/
内部的子文件夹中,可以考虑将相关内容或数据文件迁移到内容集合中。
请参考我们的手把手教程中的示例,了解如何将位于 src/pages/posts/
的基本博客示例转换为 src/content/posts
目录下的示例。该教程使用了构建博客教程的完整项目的代码库。
启用构建缓存
添加于: astro@3.5.0
实验性
如果你正在处理大量的集合,你可能希望通过 experimental.contentCollectionCache
标志启用缓存的构建。这个实验性的功能优化了 Astro 的构建过程,使得未改变的集合能够在构建之间被存储和复用。
在许多情况下,这可以导致显著的构建性能提升。
虽然这个功能正在稳定中,但你也可能会遇到与存储缓存有关的问题。所以你始终可以通过运行以下命令重置你的构建缓存:
npm run astro build -- --force
用 Remark 修改 Frontmatter
Astro 支持 remark 或者 rehype 插件直接修改 frontmatter。你可以通过使用从 render()
返回的 remarkPluginFrontmatter
属性在一个内容条目中访问这个修改过的 Frontmatter:
---
import { getEntry } from 'astro:content';
const blogPost = await getEntry('blog', 'post-1');
const { remarkPluginFrontmatter } = await blogPost.render();
---
<p>{blogPost.data.title} — {remarkPluginFrontmatter.readingTime}</p>
相关操作指南: 添加阅读时间Remark 和 rehype pipeline 只在渲染内容时运行,这就解释了为什么只有在对内容条目调用 render()
之后才可以使用 remarkPluginFrontmatter
。相比之下,getCollection()
和 getEntry()
无法直接返回这些值,因为它们不会渲染内容。
在 frontmatter 中处理日期
内容集合中可以使用多种日期格式,但你的集合 schema 必须匹配你在 Markdown 或 MDX YAML 中 frontmatter 所使用的格式。
YAML 使用 ISO-8601 标准来表示日期,其以 yyyy-mm-dd
格式(例如 2021-07-28
)表示并配合 z.date()
的 schema 类型来使用:
---
title: 我的博客文章
pubDate: 2021-07-08
---
如果没有提供时区,日期格式将指定为 UTC 格式。如果你需要指定一个时区,你可以使用 ISO 8601 格式。
src/pages/posts/example-post.md---
title: 我的博客文章
pubDate: 2021-07-08T12:00:00-04:00
---
想要仅渲染完整 UTC 时间戳中的 YYYY-MM-DD
,可以使用 JavaScript 的 slice
方法来移除时间戳:
---
const { frontmatter } = Astro.props;
---
<h1>{frontmatter.title}</h1>
<p>{frontmatter.pubDate.toISOString().slice(0,10)}</p>
要查看使用 toLocaleDateString
格式化日期、月份和年份的例子,请查看官方 Astro 博客模板中的 <FormattedDate />
组件。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论