Astro 内容加载器 API
Astro 的内容加载器(Content Loader)API 允许你从任意来源(本地或远程)载入数据,并与 Astro 的 content layer 交互以管理你的 内容集合。
该 API 包含两个可直接使用的加载器,用于加载本地存储的内容。它还提供了用于构建自定义对象的工具,可将任意来源的数据加载到内容集合中。
在内容集合指南中,通过引导式解释和示例用法,了解更多关于 查询从构建时加载器加载的数据 或 从实时加载器访问实时数据 的内容。
构建时加载器
Section titled “构建时加载器”构建时加载器是具有 load() 方法 的对象,该方法在构建时被调用以获取数据并更新数据存储。此对象还可以为条目定义一个 schema,用于验证数据并生成静态类型。
Astro 的 glob() 和 file() 加载器是开箱即用的对象加载器示例,用于处理本地内容。对于远程内容,则没有提供预置的加载器。你需要自行构建一个对象加载器,或使用 社区发布的加载器 来获取远程内容并与数据存储进行交互。
对于简单的数据请求,你也可以 将加载器定义为一个异步函数,该函数返回一个包含条目的数组或对象。
glob() 加载器
Section titled “glob() 加载器”类型: (options: GlobOptions) => Loader
astro@5.0.0
glob() 加载器从文件系统中任何位置的文件目录创建条目。支持的文件类型包括 Markdown、MDX、Markdoc、JSON、YAML 和 TOML 文件。
该加载器接受具有以下属性的对象:pattern、base(可选)、generateId(可选)和 retainBody(可选)。
import { defineCollection } from 'astro:content';import { glob } from 'astro/loaders';
const pages = defineCollection({ /* 检索你 page 目录中的所有 Markdown 文件。 */ loader: glob({ pattern: "**/*.md", base: "./src/data/pages" }),});const blog = defineCollection({ /* 检索你 blog 目录中的所有 Markdown 和 MDX 文件。 */ loader: glob({ pattern: "**/*.(md|mdx)", base: "./src/data/blog" }),});const notes = defineCollection({ /* 在你的笔记目录中检索所有 Markdown 文件并防止 * 内容文件的原始正文被存储到数据存储中。 */ loader: glob({ pattern: '**/*.md', base: './src/data/notes', retainBody: false }),});const authors = defineCollection({ /* 检索你 authors 目录中的所有 JSON 文件, * 同时保留 ID 中的大写字母。 */ loader: glob({ pattern: '**/*.json', base: "./src/data/authors", generateId: ({ entry }) => entry.replace(/\.json$/, ''), }),});
export const collections = { pages, blog, authors };pattern
Section titled “pattern”类型: string | string[]
pattern 属性接受使用全局匹配的字符串或字符串数组(例如通配符、双星号)。pattern 必须是相对于条目文件的 base 目录才能够匹配。
你可以在 micromatch 文档 中了解到有关应用语法的更多信息。你还可以使用像 DigitalOcean Glob Tool 这样的在线工具来验证 pattern 的有效性。
类型: string | URL
默认值: "."
从中解析 pattern 目录的相对路径或 URL。
generateId()
Section titled “generateId()”类型: (options: GenerateIdOptions) => string
返回集合中每个条目的唯一字符串的回调函数。它接受具有以下属性的对象作为参数:
entry- 条目文件的路径,相对于 base 目录base- base 目录的 URLdata- 条目中已解析、未经验证的数据
默认情况下,它使用 github-slugger 生成遵循 烤串命名法 的 slug。
retainBody
Section titled “retainBody”类型: boolean
默认值: true
astro@5.17.0
是否在数据存储中保存内容文件的原始正文。
当 retainBody 设置为 false 时,entry.body 将被设置为 undefined,而不是包含原始文件内容。
将此属性设置为 false 可以显著减少部署的数据存储大小,并有助于避免在拥有非常大集合的网站上触及大小限制。。
对于 Markdown 文件,渲染后的正文仍可在 entry.rendered.html 属性 中获取,且 entry.filePath 属性 仍将指向原始文件。
对于 MDX 集合,这将大幅减小集合的大小,因为存储中将不再保留任何正文。
file() 加载器
Section titled “file() 加载器”类型: (fileName: string, options?: FileOptions) => Loader
astro@5.0.0
file() 加载器从单个文件创建条目,该文件包含具有唯一 id 字段的对象数组或是一个以 ID 作为键、条目作为值的对象。
它支持 JSON、YAML 或者 TOML 文件,你可以为默认情况下无法解析的数据文件提供一个自定义 parser 或者用于异步解析数据。
该加载器接受一个 fileName 属性和一个可选对象作为第二个参数:
import { defineCollection } from 'astro:content';import { file } from 'astro/loaders';
const authors = defineCollection({ /* 从一个 JSON 文件中检索所有条目。 */ loader: file("src/data/authors.json"),});const products = defineCollection({ /* 使用自定义 parser 从一个 CSV 文件中检索所有条目。 */ loader: file("src/data/products.csv", { parser: (fileContent) => { /* 你的 parser 逻辑 */ }, }),});
export const collections = { authors, products };fileName
Section titled “fileName”类型: string
设置要加载的文件的路径,相对于根目录。
类型: FileOptions
具有以下属性的可选对象:
parser()
Section titled “parser()”类型: (text: string) => Record<string, Record<string, unknown>> | Array<Record<string, unknown>> | Promise<Record<string, Record<string, unknown>> | Array<Record<string, unknown>>>
回调函数,用于从文件内容创建一个集合。当你需要处理 JSON, YAML 或者 TOML 之外的默认情况下不支持的文件(例如 .csv)或使用 嵌套的 .json 文档 时,请使用它。
构建一个加载器
Section titled “构建一个加载器”Content Loader API 灵活且功能完善,支持多种数据获取方式。你可以构建简单或复杂的加载器。你的自定义加载器将取决于数据的来源和结构,以及你选择如何管理持久化数据存储层。
大多数加载器会导出一个函数,该函数接受配置选项并返回一个 加载器对象,其中包括加载器的 name、一个 load() 方法以及定义条目的 schema。
将集合加载到数据存储中
Section titled “将集合加载到数据存储中”loader 对象中返回的 load() 函数定义了如何获取、解析、验证和更新你的内容。它接受一个 context 对象,允许你以多种方式自定义数据处理并与数据存储进行交互。一个典型的 load() 函数将会:
- 从数据源获取你的数据。
- 清除现有的数据存储。
- 根据提供的模式解析并验证你的数据条目。
- 使用新条目更新数据存储。
load() 方法还提供了一些辅助功能,用于将消息记录到控制台、将内容渲染为 HTML、在开发模式下监听变化并重新加载数据、提供对元数据乃至完整 Astro 配置的访问,以及更多其他功能。
LoaderContext 属性列表,了解 load() 函数的所有可用选项。
提供一个 schema 模式
Section titled “提供一个 schema 模式”在加载器中提供 Zod schema 模式,可让你在将获取的内容条目添加到数据 存储 之前,使用 parseData() 对其进行验证。当 src/content.config.ts 中不存在 schema 模式时,该模式还将作为集合的默认模式,以提供类型安全和编辑器工具支持。如果加载器已提供此属性,则无需在内容集合中再额外定义模式。
但是,如果内容集合也 定义了 schema 模式,则将使用该模式而非加载器的模式。这是为了允许加载器的用户扩展其 schema 模式,或转换数据以在其项目中使用。如果你正在 发布和分发供他人使用的加载器,你可能希望记录此行为,并建议用户不要自行定义集合模式,或者如果他们需要以不同格式返回数据时,应如何安全地执行此操作。
如果你需要根据配置选项或通过内省 API 来动态生成模式,可以改用 createSchema()。
以下示例展示了一个加载器,它从提供的 feed URL 获取数据(使用自定义的 loadFeedData 工具),并在每次构建网站时将新条目更新到数据存储中:
// 1. 导入 `Loader` 类型以及其他所需的依赖项import type { Loader } from 'astro/loaders';import { z } from 'astro/zod';import { loadFeedData } from "./feed.js";
// 2. 定义你的加载器所需的任何选项export function feedLoader(options: { url: string, apiKey: string }) { const feedUrl = new URL(options.url); // 3. 返回一个加载器对象 return { name: "feed-loader", load: async ({ store, parseData }) => { const feed = await loadFeedData(feedUrl, options.apiKey);
store.clear();
for (const item of feed.items) { const id = item.guid; const data = await parseData({ id, data: item, }); store.set({ id, data, }); } }, // 4. 定义条目的模式 schema: z.object({ // ... }) } satisfies Loader;}使用你的加载器定义你的集合
Section titled “使用你的加载器定义你的集合”在 src/content.config.ts 中定义集合时,将自定义加载器作为 loader 属性的值使用。配置选项可以作为参数传递给加载器:
import { defineCollection } from 'astro:content';import { feedLoader } from './feed-loader.ts';
const blog = defineCollection({ loader: feedLoader({ url: "https://api.example.com/posts", apiKey: "my-secret", }),});
export const collections = { blog };将加载器定义为函数
Section titled “将加载器定义为函数”对于不需要自定义数据存储处理、验证、日志记录或 构建时加载器对象 所提供的任何其他辅助功能的简单数据获取,你可以将加载器定义为一个函数。
该函数可以是异步的,且必须返回一个数组(数组中每个条目都包含唯一的 id 字段),或者返回一个对象(其中每个键是唯一的 ID,每个值是对应的条目)。
该模式提供了一种便捷的简写方式,用于完成通常由 load() 函数执行的基本任务,即 将集合加载到数据存储中。在构建时,加载器将自动清除数据存储并重新加载所有条目。不提供任何进一步的自定义选项或数据处理辅助工具。
这些加载器通常足够简单,你可以选择在 src/content.config.ts 文件中以内联方式定义它们:
import { defineCollection } from "astro:content";
const countries = defineCollection({ loader: async () => { const response = await fetch("https://restcountries.com/v3.1/all"); const data = await response.json(); // 必须返回一个包含 id 属性的条目数组, // 或者一个以 ID 为键、条目为值的对象 return data.map((country) => ({ id: country.cca3, ...country, })); },});
export const collections = { countries };实时加载器 API 专为实时查询任意数据而构建。实时加载器可以过滤传入数据,并通过类型安全验证内容。由于实时加载器在每次请求时都会重新获取最新数据,因此无需更新数据存储。实时加载器设计为返回数据或 Error 对象,以便你能够优雅地处理错误。
构建实时加载器
Section titled “构建实时加载器”大多数实时加载器会导出一个函数,该函数接受配置选项并返回一个 实时加载器对象,其中包括加载器的 name 以及两个用于定义如何加载条目集合和如何加载单个条目的方法:loadCollection() 和 loadEntry()。
加载实时数据
Section titled “加载实时数据”要返回有关集合的数据,你必须提供一个用于获取数据的 loadCollection() 函数,并返回一个内容 entries 数组或一个错误。
要返回单个实时集合条目,你必须提供一个获取按给定 id 过滤的数据的 loadEntry() 函数,返回单个 entry、undefined 或一个错误。
这两个函数的数据获取通常使用 try...catch 语句 来 处理访问实时数据时的错误。
为实时加载器提供模式
Section titled “为实时加载器提供模式”实时加载器不包含 schema 模式属性。相反,你可以通过在 src/live.config.ts 中 为你的集合定义 Zod 模式,或者通过将泛型类型传递给 LiveLoader 接口来为其返回的数据提供类型安全。
示例实时加载器
Section titled “示例实时加载器”以下示例展示了一个实时加载器,它定义了从 CMS 获取数据的方式(使用自定义的 fetchFromCMS 工具),涵盖条目集合和单个条目的获取,包括类型安全和错误处理:
import type { LiveLoader } from 'astro/loaders';import { fetchFromCMS } from './cms-client.js';
interface Article { id: string; title: string; htmlContent: string; author: string;}
interface EntryFilter { id: string;}
interface CollectionFilter { author?: string;}
export function articleLoader(config: { apiKey: string }): LiveLoader<Article, EntryFilter, CollectionFilter> { return { name: 'article-loader', loadCollection: async ({ filter }) => { try { const articles = await fetchFromCMS({ apiKey: config.apiKey, type: 'article', filter, });
return { entries: articles.map((article) => ({ id: article.id, data: article, })), }; } catch (error) { return { error: new Error('Failed to load articles', { cause: error }), }; } }, loadEntry: async ({ filter }) => { try { // 当使用字符串调用时,filter 将为 { id: "some-id" } const article = await fetchFromCMS({ apiKey: config.apiKey, type: 'article', id: filter.id, });
if (!article) { return { error: new Error('Article not found'), }; }
return { id: article.id, data: article, rendered: { html: article.htmlContent, }, }; } catch (error) { return { error: new Error('Failed to load article', { cause: error }), }; } }, };}使用加载器定义你的实时集合
Section titled “使用加载器定义你的实时集合”在 src/live.config.ts 中定义集合时,将自定义实时加载器作为 loader 属性的值使用。配置选项可以作为参数传递给加载器:
import { defineLiveCollection } from 'astro:content';import { articleLoader } from './article-loader.ts';
const blog = defineLiveCollection({ loader: articleLoader({ apiKey: "my-secret", }),});
export const collections = { blog };实时加载器中的错误处理
Section titled “实时加载器中的错误处理”实时加载器为错误返回一个 Error 子类。如果需要,你可以创建 自定义错误类型 并将其用于更具体的错误处理。如果在实时加载器中抛出错误,它将被捕获并返回,包装在 LiveCollectionError 中。
Astro 将根据实时加载器的响应自行生成一些错误:
- 如果
loadEntry返回undefined, Astro 将会返回LiveEntryNotFoundError给用户。 - 如果为集合定义了 schema 且数据与 schema 不匹配,Astro 将会返回
LiveCollectionValidationError。 - 如果加载器返回了无效的缓存提示,Astro 将会返回
LiveCollectionCacheHintError。cacheHint字段是可选的,因此如果你没有有效的数据可返回,可以直接省略它。
import type { LiveLoader } from 'astro/loaders';import type { MyData } from "./types";import { MyLoaderError } from './errors';
export function myLoader(config): LiveLoader<MyData, never, never, MyLoaderError> { return { name: 'my-loader', loadCollection: async () => { // 返回你的自定义错误类型 return { error: new MyLoaderError('Failed to load', 'LOAD_ERROR'), }; }, // ... };}创建实时加载器错误类型
Section titled “创建实时加载器错误类型”你可以为 加载器返回的错误 创建自定义错误类型,并将它们作为泛型传递以获得正确的类型:
import type { LiveLoader } from "astro/loaders";import type { MyData } from "./types"
export class MyLoaderError extends Error { constructor(message: string, public code?: string) { super(message); this.name = 'MyLoaderError'; }}
export function myLoader(config): LiveLoader<MyData, never, never, MyLoaderError> { return { name: 'my-loader', loadCollection: async () => { // 返回你的自定义错误类型 return { error: new MyLoaderError('Failed to load', 'LOAD_ERROR'), }; }, // ... };}当你使用 getLiveCollection() 或 getLiveEntry() 时,TypeScript 会推断自定义错误类型,让你能够对应地处理它:
---export const prerender = false; // Not needed in 'server' mode
import { getLiveEntry } from 'astro:content';import { MyLoaderError } from "../my-loader";
const { entry, error } = await getLiveEntry('products', '123');
if (error) { if (error instanceof MyLoaderError) { console.error(`Loader error: ${error.message} (code: ${error.code})`); } else { console.error(`Unexpected error: ${error.message}`); } return Astro.rewrite('/500');}---定义自定义筛选器类型
Section titled “定义自定义筛选器类型”实时加载器可以为 getLiveCollection() 和 getLiveEntry() 定义自定义筛选器类型。这会启用匹配你的 API 能力的类型安全的查询,让用户更容易发现可用的筛选器并确保正确使用。如果在筛选器类型中包含 JSDoc 注释,用户在使用加载器时将在其 IDE 中看到这些提示。
import type { LiveLoader } from 'astro/loaders';import { fetchProduct, fetchCategory, type Product } from './store-client';
interface CollectionFilter { category?: string; /** 筛选产品的最低价格 */ minPrice?: number; /** 筛选产品的最高价格 */ maxPrice?: number;}
interface EntryFilter { /** `sku` 的别名 */ id?: string; slug?: string; sku?: string;}
export function productLoader(config: { apiKey: string; endpoint: string;}): LiveLoader<Product, EntryFilter, CollectionFilter> { return { name: 'product-loader', loadCollection: async ({ filter }) => { // filter 被类型化为 CollectionFilter const data = await fetchCategory({ apiKey: config.apiKey, category: filter?.category ?? 'all', minPrice: filter?.minPrice, maxPrice: filter?.maxPrice, });
return { entries: data.products.map((product) => ({ id: product.sku, data: product, })), }; }, loadEntry: async ({ filter }) => { // filter 被类型化为 EntryFilter | { id: string } const product = await fetchProduct({ apiKey: config.apiKey, slug: filter.slug, sku: filter.sku || filter.id, }); if (!product) { return { error: new Error('Product not found'), }; } return { id: product.sku, data: product, }; }, };}实时加载器可以提供缓存提示,以帮助进行响应缓存。你可以使用这些数据来发送 HTTP 缓存头,或以其他方式告知你的缓存策略。
import type { LiveLoader } from "astro/loaders";import { loadStoreProduct, loadStoreProducts, getLastModifiedDate } from "./store";import type { Product, ProductEntryFilter, ProductCollectionFilter } from "./types";
export function myLoader(config): LiveLoader<Product, ProductEntryFilter, ProductCollectionFilter> { return { name: 'cached-loader', loadCollection: async ({ filter }) => { const products = await loadStoreProducts(filter); return { entries: products.map((item) => ({ id: item.id, data: item, // 你可以为每个条目选择性地提供缓存提示 cacheHint: { tags: [`product-${item.id}`, `category-${item.category}`], }, })), cacheHint: { // 所有字段都是可选的,并与每个条目的缓存提示合并 // tags 从所有条目中合并 // lastModified 是所有条目和集合中最新的 lastModified lastModified: getLastModifiedDate(products), tags: ['products'], }, }; }, loadEntry: async ({ filter }) => { const item = await loadStoreProduct(filter); return { id: item.id, data: item, cacheHint: { lastModified: new Date(item.lastModified), tags: [`product-${item.id}`, `category-${item.category}`], }, }; }, };}然后你可以在你的页面中使用这些提示。如果你启用了 实验性路由缓存 (EN),请直接将缓存提示传递给 Astro.cache.set():
---export const prerender = false; // 无需 'server' 模式
import { getLiveEntry } from 'astro:content';
const { entry, error, cacheHint } = await getLiveEntry('products', Astro.params.id);
if (error) { return Astro.redirect('/404');}
// 传递缓存提示给路由缓存if (cacheHint) { Astro.cache.set(cacheHint);}Astro.cache.set({ maxAge: 300 });---
<h1>{entry.data.name}</h1><p>{entry.data.description}</p>在未启用路由缓存的情况下,你可以使用缓存提示手动设置响应标头,以实现你自己的缓存策略:
---export const prerender = false; // 无需 'server' 模式
import { getLiveEntry } from 'astro:content';
const { entry, error, cacheHint } = await getLiveEntry('products', Astro.params.id);
if (error) { return Astro.redirect('/404');}
if (cacheHint?.tags) { Astro.response.headers.set('Cache-Tag', cacheHint.tags.join(','));}
if (cacheHint?.lastModified) { Astro.response.headers.set('Last-Modified', cacheHint.lastModified.toUTCString());}---
<h1>{entry.data.name}</h1><p>{entry.data.description}</p>缓存提示不会自动让响应被 Astro 缓存。它们仅提供可以传递给 路由缓存 (EN) 的值,或者用于实现你自己的缓存策略。
分发你的加载器
Section titled “分发你的加载器”加载器可以在你的网站中定义,也可以作为单独的 npm 包。如果你想与社区分享你的加载器,可以 使用 withastro 和 astro-loader 关键词将其发布到 npm (EN)。
加载器应导出一个函数,该函数为实时加载器返回 LiveLoader 对象,或为构建时加载器返回 Loader 对象,从而允许用户使用他们自己的设置进行配置。
对象加载器 API
Section titled “对象加载器 API”
添加于:
astro@5.0.0
本节展示了用于定义 构建时对象加载器 的 API。
Loader 对象
Section titled “Loader 对象”类型: Loader
加载器函数返回一个包含两个必需属性的对象。除了为加载器提供名称外,该对象还描述了如何获取集合数据。
可选地,你可以返回第三个属性来定义一个用于验证集合条目的模式。使用 TypeScript 的 satisfies 操作符,而不是返回类型注解,以便在加载器对象内部提供类型安全,并在加载器用于集合时保留类型推断。
Loader.name
Section titled “Loader.name”类型: string
astro@5.0.0
加载器的唯一名称,用于日志和 条件性加载。
Loader.load()
Section titled “Loader.load()”类型: (context: LoaderContext) => Promise<void>
astro@5.0.0
它会接收一个 LoaderContext 对象,该对象包含用于编写加载器实现逻辑的辅助函数和属性,以及 store 数据库和与其交互的方法。
Loader.schema
Section titled “Loader.schema”类型: ZodSchema
astro@5.0.0
一个可选的 Zod 模式,用以定义条目的结构。它既可用于验证数据,也可用于为集合生成 TypeScript 类型。
当你需要基于配置选项或通过内省 API 在构建时动态生成模式时,请改用 createSchema()。
如果存在,它将被 src/content.config.ts 文件中为集合定义的任何 Zod schema 覆盖。
Loader.createSchema()
Section titled “Loader.createSchema()”类型: () => Promise<{ schema: ZodSchema; types: string }>
astro@6.0.0
一个可选的异步函数,返回一个包含 Zod 模式 和类型的对象。它用于在构建时根据配置选项或通过 API 自省来动态生成模式。
当你只需要提供一个静态模式时,请改用 schema 提供一个 Zod 验证对象。
如果存在,它将被 src/content.config.ts 文件中为该集合定义的任何 Zod schema 覆盖。
返回的 types 内容将被写入一个 TypeScript 文件,并且必须导出一个 Entry 类型或接口:
import type { Loader } from 'astro/loaders';import { z } from 'astro/zod';import { loadFeedData, getSchema, getTypes } from "./feed.js";
export function myLoader(options: { url: string, apiKey: string }) { const feedUrl = new URL(options.url);
return { name: "feed-loader", load: async ({ store, parseData }) => { const feed = await loadFeedData(feedUrl, options.apiKey);
store.clear();
for (const item of feed.items) { const id = item.guid; const data = await parseData({ id, data: item, }); store.set({ id, data, }); } }, createSchema: async () => { const schema = await getSchema(); const types = await getTypes();
return { schema, types: `export type Entry = ${types}`, }; }, } satisfies Loader;}LoaderContext
Section titled “LoaderContext”该对象将被传递给加载器的 load() 方法,并包含以下属性:
LoaderContext.collection
Section titled “LoaderContext.collection”类型: string
astro@5.0.0
集合的唯一名称。这是 src/content.config.ts 文件中 collections 对象的键。
LoaderContext.store
Section titled “LoaderContext.store”类型: DataStore
astro@5.0.0
存储实际数据的数据库。使用它可以用新条目更新存储部分。有关更多信息,请参阅 DataStore。
LoaderContext.meta
Section titled “LoaderContext.meta”类型: MetaStore
astro@5.0.0
范围为集合的键值存储,专为同步令牌和上次修改时间等内容而设计。此元数据在构建之间与集合数据一起保留,但仅在加载器内部可用。
const lastModified = meta.get("lastModified");// ...meta.set("lastModified", new Date().toISOString());LoaderContext.logger
Section titled “LoaderContext.logger”astro@5.0.0
一个可用于向控制台记录消息的日志记录器。请使用此工具代替 console.log,以获得更有帮助的日志,其中包含加载器特定的内容,例如加载器名称或日志消息中有关加载过程的信息。有关更多信息,请参阅 AstroIntegrationLogger。
return { name: 'file-loader', load: async ({ config, store, logger, watcher }) => { const url = new URL(fileName, config.root); const filePath = fileURLToPath(url); await syncData(filePath, store);
watcher?.on('change', async (changedPath) => { if (changedPath === filePath) { logger.info(`Reloading data from ${fileName}`); await syncData(filePath, store); } }); },};LoaderContext.config
Section titled “LoaderContext.config”类型: AstroConfig
astro@5.0.0
应用了所有默认值的完整、已解析的 Astro 配置对象。有关更多信息,请参阅 配置参考。
return { name: 'file-loader', load: async ({ config, store, logger, watcher }) => { const url = new URL(fileName, config.root); const filePath = fileURLToPath(url); await syncData(filePath, store);
watcher?.on('change', async (changedPath) => { if (changedPath === filePath) { logger.info(`Reloading data from ${fileName}`); await syncData(filePath, store); } }); },};LoaderContext.parseData()
Section titled “LoaderContext.parseData()”类型: (props: ParseDataOptions<TData>) => Promise<TData>
astro@5.0.0
根据集合模式验证和解析数据。将数据传递给该函数以在将其存储到数据存储中之前,对其进行验证和解析。
import type { Loader } from "astro/loaders";import { loadFeed } from "./feed.js";
export function feedLoader({ url }) { const feedUrl = new URL(url); return { name: "feed-loader", load: async ({ store, logger, parseData, meta, generateDigest }) => { logger.info("Loading posts"); const feed = loadFeed(feedUrl); store.clear();
for (const item of feed.items) { const id = item.guid; const data = await parseData({ id, data: item, }); store.set({ id, data, }); } }, } satisfies Loader;}LoaderContext.renderMarkdown()
Section titled “LoaderContext.renderMarkdown()”类型: (content: string, options?: { fileURL?: URL }) => Promise<RenderedContent>
astro@5.9.0
用于将 Markdown 字符串渲染为 HTML,返回一个 RenderedContent 对象。
该功能允许你在加载器中直接渲染 Markdown 内容,其处理逻辑与 Astro 内置的 glob() 加载器完全一致,该功能可以调用 render() 函数处理原始内容,并使用 <Content /> 组件 渲染正文内容。
将该对象分配给 DataEntry 对象的 rendered 字段,以允许用户 在页面中渲染内容。如果 Markdown 内容包含 frontmatter,它将被解析并可在 metadata.frontmatter 中使用。frontmatter 将被排除在 HTML 输出之外。
import type { Loader } from 'astro/loaders';import { loadFromCMS } from './cms.js';
export function myLoader(settings) { return { name: 'cms-loader', async load({ renderMarkdown, store }) { const entries = await loadFromCMS();
store.clear();
for (const entry of entries) { store.set({ id: entry.id, data: entry, // 假设每个条目都包含一个带有 markdown 内容的 'content' 字段 rendered: await renderMarkdown(entry.content), }); } }, } satisfies Loader;}fileURL
Section titled “fileURL”类型: URL
astro@6.0.0
指定用于解析 Markdown 内容中相对图片路径的文件路径。
以下示例使用 配置的根目录 来解析图片路径:
for (const file of files) { const content = await readFile(file.path, 'utf8'); store.set({ id: file.id, data: file.data, rendered: await renderMarkdown(content, { fileURL: new URL(file.path, config.root), }), });}LoaderContext.generateDigest()
Section titled “LoaderContext.generateDigest()”类型: (data: Record<string, unknown> | string) => string
astro@5.0.0
生成对象或字符串的非加密内容摘要。这可用于通过设置条目的 digest 字段 来跟踪数据是否已更改。
import type { Loader } from "astro/loaders";import { loadFeed } from "./feed.js";
export function feedLoader({ url }) { const feedUrl = new URL(url); return { name: "feed-loader", load: async ({ store, logger, parseData, meta, generateDigest }) => { logger.info("Loading posts"); const feed = loadFeed(feedUrl); store.clear();
for (const item of feed.items) { const id = item.guid; const data = await parseData({ id, data: item, });
const digest = generateDigest(data);
store.set({ id, data, digest, }); } }, } satisfies Loader;}LoaderContext.watcher
Section titled “LoaderContext.watcher”类型:: FSWatcher
astro@5.0.0
当在开发模式下运行时,这是一个文件系统监听器,可用于触发更新。有关更多信息,请参阅 ViteDevServer。
return { name: 'file-loader', load: async ({ config, store, watcher }) => { const url = new URL(fileName, config.root); const filePath = fileURLToPath(url); await syncData(filePath, store);
watcher?.on('change', async (changedPath) => { if (changedPath === filePath) { logger.info(`Reloading data from ${fileName}`); await syncData(filePath, store); } }); },};LoaderContext.refreshContextData
Section titled “LoaderContext.refreshContextData”类型: Record<string, unknown>
astro@5.0.0
如果加载器已经由集成触发,则可以选择性地包含该由集成所设置的额外数据。仅当加载器是被集成触发时才会设置。有关更多信息,请参阅 astro:server:setup 钩子参考。
import type { Loader } from "astro/loaders";import { processWebhook } from "./lib/webhooks";
export function myLoader(options: { url: string }) { return { name: "my-loader", load: async ({ refreshContextData, store, logger }) => { if(refreshContextData?.webhookBody) { logger.info("Webhook triggered with body"); processWebhook(store, refreshContextData.webhookBody); } // ... }, } satisfies Loader;}DataStore
Section titled “DataStore”数据存储是内容集合数据的加载器接口。它是一个键值(KV)存储,范围仅限于集合,因此加载器只能访问其自己集合的数据。
DataStore.get()
Section titled “DataStore.get()”类型: (key: string) => DataEntry | undefined
astro@5.0.0
通过其 ID 从存储获取条目。如果条目不存在,则返回 undefined。
const existingEntry = store.get("my-entry");返回的对象是一个 DataEntry 对象。
DataStore.set()
Section titled “DataStore.set()”类型: (entry: DataEntry) => boolean
astro@5.0.0
在数据被 验证和解析 之后使用,从而将条目添加到存储中。如果设置了条目则返回 true。当 digest 属性确定条目未更改且不应更新时,则返回 false。
for (const item of feed.items) { const id = item.guid; const data = await parseData({ id, data: item, }); const digest = generateDigest(data); store.set({ id, data, rendered: { html: data.description ?? "", }, digest, }); }DataStore.entries()
Section titled “DataStore.entries()”类型: () => Array<[id: string, DataEntry]>
astro@5.0.0
获取集合中的所有条目作为键值对数组。
DataStore.keys()
Section titled “DataStore.keys()”类型: () => Array<string>
astro@5.0.0
获取集合中所有条目的键。
DataStore.values()
Section titled “DataStore.values()”类型: () => Array<DataEntry>
astro@5.0.0
获取集合中的所有条目作为数组。
DataStore.delete()
Section titled “DataStore.delete()”类型: (key: string) => void
astro@5.0.0
通过条目的 ID 从存储中删除条目。
DataStore.clear()
Section titled “DataStore.clear()”类型: () => void
astro@5.0.0
清除集合中的所有条目。
DataStore.has()
Section titled “DataStore.has()”类型: (key: string) => boolean
astro@5.0.0
通过条目的 ID 从存储中检查是否存在该条目。
DataEntry
Section titled “DataEntry”这是存储在数据存储中的对象的类型。它具有以下属性:
DataEntry.id
Section titled “DataEntry.id”类型: string
astro@5.0.0
条目的标识符,在集合中必须是唯一的。它用于查找存储中的条目,同时也是与该集合的 getEntry() 一起使用的键。
DataEntry.data
Section titled “DataEntry.data”类型: Record<string, unknown>
astro@5.0.0
条目的实际数据。当用户访问集合时,将根据集合模式生成 TypeScript 类型。
加载器的责任为在将数据存储到数据存储之前使用 parseData 来验证和解析数据:获取或设置数据时不进行验证。
DataEntry.filePath
Section titled “DataEntry.filePath”类型: string | undefined
astro@5.0.0
作为此条目源的文件路径(相对于站点的根目录)。这仅适用于基于文件的加载器,并用于解析图像或其他资源等路径。
如果未设置,则模式中使用 image() 助手函数 的任何字段都将被视为位于 public 路径 下而跳过图像优化。
DataEntry.body
Section titled “DataEntry.body”类型: string | undefined
astro@5.0.0
条目的原始正文(如果适用的话)。如果条目包含了 渲染内容,则该字段可用于存储原始源。该属性为可选项,内部不使用。
DataEntry.digest
Section titled “DataEntry.digest”类型: string | undefined
astro@5.0.0
条目的可选内容摘要。该属性可用于检查数据是否已更改。
当 添加条目 时,只有当摘要与具有相同 ID 的现有条目不匹配时,该条目才会更新。
摘要的格式由加载器决定,但它必须是一个随数据变化而变化的字符串。这可以通过 generateDigest 函数来完成。
DataEntry.rendered
Section titled “DataEntry.rendered”类型: RenderedContent | undefined
astro@5.0.0
存储带有条目的渲染内容和元数据(如果已渲染为 HTML)的对象。例如,这可用于存储 Markdown 条目的渲染内容或 CMS 中的 HTML。
如果提供此字段,则 render() 函数和 <Content /> 组件 可用于在页面中渲染条目。
如果条目包含 Markdown 内容,则可以使用 renderMarkdown() 函数从 Markdown 字符串生成此对象。
DataEntry.rendered.html
Section titled “DataEntry.rendered.html”类型: string
包含渲染后的 HTML 字符串。这用于 render() 返回一个渲染此 HTML 的组件。
DataEntry.rendered.metadata
Section titled “DataEntry.rendered.metadata”类型: object | undefined
描述此文件中存在的元数据。这包括 imagePaths、headings、frontmatter 和文件中存在的任何其他元数据。当文件尚未渲染为 HTML 时,此值将为 undefined。
DataEntry.rendered.metadata.imagePaths
Section titled “DataEntry.rendered.metadata.imagePaths”类型: string[]
指定此条目中存在的图像路径列表。每个路径相对于 条目的 filePath。
DataEntry.rendered.metadata.headings
Section titled “DataEntry.rendered.metadata.headings”类型: MarkdownHeading[]
指定此文件中存在的标题列表。每个标题由标题级别(h1 -> h6)确定的 depth、由 github-slugger 生成的 slug 和其 text 内容描述。
DataEntry.rendered.metadata.frontmatter
Section titled “DataEntry.rendered.metadata.frontmatter”类型: Record<string, any>
描述从文件中解析的原始前置数据。这可能包括 由 remark 插件以编程方式注入的数据。
实时加载器 API
Section titled “实时加载器 API”
添加于:
astro@6.0.0
本部分展示了用于定义 实时加载器 的 API。
LiveLoader 对象
Section titled “LiveLoader 对象”类型: LiveLoader<TData, TEntryFilter, TCollectionFilter, TError>
astro@6.0.0
实时加载器函数返回一个具有三个必需的实时加载器属性的对象。除了为加载器提供名称外,该对象还描述了如何从实时数据源中获取单个条目和整个集合。
使用 LiveLoader 泛型为你的加载器提供类型安全。此类型按以下顺序接受以下类型参数:
TData(默认为Record<string, unknown>):加载器返回的每个条目的数据结构。TEntryFilter(默认为never):getLiveEntry()接受的筛选对象类型,在loadEntry()中可访问。当不支持筛选单个条目时,使用never。TCollectionFilter(默认为never):getLiveCollection()接受的筛选对象类型,在loadCollection()中可访问。当不支持筛选单个条目时,使用never。TError(默认为Error):加载器可以返回的 自定义Error类,用于更细粒度的错误处理。
LiveLoader.name
Section titled “LiveLoader.name”类型: string
astro@6.0.0
加载器的唯一名称,用于日志中。
LiveLoader.loadCollection()
Section titled “LiveLoader.loadCollection()”类型: (context: LoadCollectionContext<TCollectionFilter>) => Promise<LiveDataCollection<TData> | { error: TError; }>
astro@6.0.0
定义一个加载条目集合的方法。此函数接收一个包含可选 filter 属性的 上下文对象,并且必须返回与此集合关联的数据或错误。
LiveLoader.loadEntry()
Section titled “LiveLoader.loadEntry()”类型: (context: LoadEntryContext<TEntryFilter>) => Promise<LiveDataEntry<TData> | undefined | { error: TError; }>
astro@6.0.0
定义了一个加载单个条目的方法。此函数接收一个包含 filter 属性的 上下文对象,并返回与请求的条目相关联的数据、当找不到该条目时返回 undefined,或返回错误信息。
LoadCollectionContext
Section titled “LoadCollectionContext”类型: { filter?: TCollectionFilter; }
astro@6.0.0
该对象被传递给加载器的 loadCollection() 方法,并包含以下属性:
LoadCollectionContext.filter
Section titled “LoadCollectionContext.filter”类型: Record<string, any> | never
默认值: never
astro@6.0.0
一个描述 你的加载器支持的筛选器 的对象。
LoadEntryContext
Section titled “LoadEntryContext”类型: { filter: TEntryFilter; }
astro@6.0.0
该对象被传递给加载器的 loadEntry() 方法,并包含以下属性:
LoadEntryContext.filter
Section titled “LoadEntryContext.filter”类型: Record<string, any> | never
默认值: never
astro@6.0.0
一个描述 你的加载器支持的筛选器 的对象。
LiveDataEntry
Section titled “LiveDataEntry”类型: { id: string; data: TData; rendered?: { html: string }; cacheHint?: CacheHint; }
astro@6.0.0
这是由 loadEntry() 方法返回的类型对象。它包含以下属性:
LiveDataEntry.id
Section titled “LiveDataEntry.id”类型: string
astro@6.0.0
条目的标识符,在集合中必须是唯一的。这是与该集合的 getLiveEntry()方法一起使用的键。
LiveDataEntry.data
Section titled “LiveDataEntry.data”类型: Record<string, unknown>
astro@6.0.0
条目的实际数据。当用户访问集合时,将根据集合模式生成相应的 TypeScript 类型。
加载器负责在返回数据之前验证和解析数据。
LiveDataEntry.rendered
Section titled “LiveDataEntry.rendered”类型: { html: string }
astro@6.0.0
一个包含条目已渲染内容的对象,如果该内容已被渲染为 HTML。例如,这可以是 Markdown 条目的渲染内容,或来自 CMS 的 HTML。
如果提供了此字段,则 render() 函数和 <Content /> 组件 可用于在页面中渲染条目。
如果加载器没有为条目返回 rendered 属性,<Content /> 组件将不会渲染任何内容。
LiveDataEntry.cacheHint
Section titled “LiveDataEntry.cacheHint”类型: CacheHint
astro@6.0.0
一个可选对象,用于提供关于如何缓存此特定条目的提示。
LiveDataCollection
Section titled “LiveDataCollection”类型: { entries: Array<LiveDataEntry<TData>>; cacheHint?: CacheHint; }
astro@6.0.0
这是由 loadCollection() 方法返回的类型对象。它包含以下属性:
LiveDataCollection.entries
Section titled “LiveDataCollection.entries”类型: Array<LiveDataEntry<TData>>
astro@6.0.0
一个 LiveDataEntry 对象数组。
LiveDataCollection.cacheHint
Section titled “LiveDataCollection.cacheHint”类型: CacheHint
astro@6.0.0
一个可选对象,提供关于如何缓存此集合的指导。如果提供了此对象,它将与为每个单独条目定义的缓存提示合并。
CacheHint
Section titled “CacheHint”一个对象,加载器可以通过 LiveDataCollection 或 LiveDataEntry 中的 cacheHint 属性返回该对象,以提供提示来协助缓存响应。该对象包含以下属性:
CacheHint.tags
Section titled “CacheHint.tags”类型: Array<string>
astro@6.0.0
一个字符串标识符数组,允许细粒度的缓存控制。这使你能够对相关内容进行分组,并在特定内容更改时选择性地使缓存的响应失效。
以下示例为按作者筛选的文章集合定义了缓存提示标签:
return { /* ... */ cacheHint: { tags: ["posts", `posts-${filter.author}`], },};CacheHint.lastModified
Section titled “CacheHint.lastModified”类型: Date
astro@6.0.0
内容的最后修改日期(例如,集合中条目的最后更新时间)。这可用于设置 HTTP 缓存头,如 Last-Modified 和 If-Modified-Since。
以下示例使用产品的最后更新日期为单个产品定义缓存提示:
return { /* ... */ cacheHint: { lastModified: new Date(product.updatedAt) },};