Astro 内容加载器 API
Astro 的内容加载器 API 允许你从任何来源(本地或远程)加载数据,并与 Astro 的内容层交互来管理你的内容集合。
什么是加载器?
标题为“什么是加载器?”的部分Astro 加载器允许你将数据加载到内容集合中,然后在页面和组件中使用。内置的 glob()
和 file()
加载器用于从文件系统加载内容,你也可以创建自己的加载器从其他来源加载内容。
每个集合都需要在其模式中定义一个加载器。你可以在项目的 src/content.config.ts
文件中内联定义一个加载器,在多个集合之间共享一个加载器,甚至可以将你的加载器作为包发布到 NPM 与他人共享,并被收录到我们的集成库中。
内置加载器
标题为“内置加载器”的部分Astro 提供了两个内置加载器来帮助你获取集合。两者都提供了适用于各种用例的选项。
glob()
加载器
标题为“`glob()` 加载器”的部分类型: (options: GlobOptions) => Loader
astro@5.0.0
glob()
加载器从文件系统任意位置的文件目录创建条目。支持的文件类型有 Markdown、MDX、Markdoc、JSON 和 YAML 文件。
该加载器接受一个包含以下属性的对象:pattern
、base
(可选)和 generateId
(可选)。
import { defineCollection } from 'astro:content';import { glob } from 'astro/loaders';
const pages = defineCollection({ /* Retrieve all Markdown files in your pages directory. */ loader: glob({ pattern: "**/*.md", base: "./src/data/pages" }), schema: /* ... */});const blog = defineCollection({ /* Retrieve all Markdown and MDX files in your blog directory. */ loader: glob({ pattern: "**/*.(md|mdx)", base: "./src/data/blog" }), schema: /* ... */});const authors = defineCollection({ /* Retrieve all JSON files in your authors directory while retaining * uppercase letters in the ID. */ loader: glob({ pattern: '**/*.json', base: "./src/data/authors", generateId: ({ entry }) => entry.replace(/\.json$/, ''), }), schema: /* ... */});
pattern
标题为“pattern”的部分类型: string | string[]
pattern
属性接受一个使用 glob 匹配(例如通配符、globstars)的字符串或字符串数组。这些模式必须相对于要匹配的条目文件的基本目录。
你可以在 micromatch 文档中了解更多关于要使用的语法。你也可以使用像 DigitalOcean Glob Tool 这样的在线工具来验证你的模式的有效性。
base
标题为“base”的部分类型: string | URL
默认值: "."
一个相对路径或URL,用于解析 pattern
的目录。
generateId()
标题为“generateId()”的部分类型: (options: GenerateIdOptions) => string
一个回调函数,为集合中的每个条目返回一个唯一的字符串。它接受一个对象作为参数,该对象具有以下属性
entry
- 条目文件的路径,相对于基本目录base
- 基本目录的 URLdata
- 条目的已解析但未验证的数据
默认情况下,它使用 github-slugger
生成一个使用短横线命名法(kebab-cased)的 slug。
file()
加载器
标题为“`file()` 加载器”的部分类型: (fileName: string, options?: FileOptions) => Loader
astro@5.0.0
file()
加载器从单个文件中创建条目,该文件包含一个具有唯一 id
字段的对象数组,或一个以 ID 为键、以条目为值的对象。它支持 JSON 或 YAML,对于默认无法解析的数据文件,你可以提供一个自定义的 parser
。
该加载器接受一个 fileName
属性和一个可选的对象作为第二个参数
import { defineCollection } from 'astro:content';import { file } from 'astro/loaders';
const authors = defineCollection({ /* Retrieve all entries from a JSON file. */ loader: file("src/data/authors.json"), schema: /* ... */});const products = defineCollection({ /* Retrieve all entries from a CSV file using a custom parser. */ loader: file("src/data/products.csv", { parser: (fileContent) => { /* your parser logic */ }, }), schema: /* ... */});
fileName
标题为“fileName”的部分类型: string
设置要加载的文件的路径,相对于根目录。
类型: FileOptions
一个可选对象,具有以下属性
parser()
标题为“parser()”的部分类型: (text: string) => Record<string, Record<string, unknown>> | Array<Record<string, unknown>>
一个从文件内容创建集合的回调函数。当你需要处理默认不支持的文件(例如 .csv
)或使用嵌套的 .json
文档时,请使用它。
加载器类型
标题为“加载器类型”的部分加载器可以定义为一个返回条目数组的简单函数,也可以使用更强大的对象内容加载器 API,以便对加载过程进行更多控制。
内联加载器
标题为“内联加载器”的部分内联加载器是一个异步函数,返回一个包含条目的数组或对象。这适用于简单的加载器,尤其是在 src/content.config.ts
文件中内联定义的加载器。
该函数可以是异步的,并且必须返回一个条目数组(每个条目都包含一个唯一的 id
字段),或一个以唯一 ID 为键、以条目为值的对象。每当调用加载器时,它都会清除存储并重新加载所有条目。
const countries = defineCollection({ loader: async () => { const response = await fetch("https://restcountries.com/v3.1/all"); const data = await response.json(); // Must return an array of entries with an id property // or an object with IDs as keys and entries as values return data.map((country) => ({ id: country.cca3, ...country, })); }, schema: /* ... */});
对象加载器
标题为“对象加载器”的部分加载器是一个具有 load()
方法的对象,该方法在构建时被调用以获取数据并更新数据存储。它允许增量更新条目,或者仅在必要时清除存储。它还可以为条目定义一个模式,用于验证数据和生成静态类型。
推荐的模式是定义一个接受配置选项并返回加载器对象的函数,就像你通常定义 Astro 集成或 Vite 插件一样。
import type { Loader, LoaderContext } from 'astro/loaders';import { z } from 'astro:content';import { loadFeedData } from "./feed.js";
// Define any options that the loader needsexport function myLoader(options: { url: string, apiKey: string }): Loader { // Configure the loader const feedUrl = new URL(options.url); // Return a loader object return { name: "my-loader", // Called when updating the collection. load: async (context: LoaderContext): Promise<void> => { // Load data and update the store const response = await loadFeedData(feedUrl, options.apiKey); }, // Optionally, define the schema of an entry. // It will be overridden by user-defined schema. schema: async () => z.object({ // ... }) };}
然后可以在定义集合时设置这些配置选项
import { defineCollection, z } from 'astro:content';import myLoader from '../../loader.ts';
const blog = defineCollection({ loader: myLoader({ url: "https://api.example.com/posts", apiKey: "my-secret", }), schema: /* ... */});
对象加载器 API
标题为“对象加载器 API”的部分内联加载器的 API 非常简单,如上所示。本节展示了定义对象加载器的 API。
Loader
对象
标题为“Loader 对象”的部分加载器对象具有以下属性
name
标题为“name”的部分类型: string
加载器的唯一名称,用于日志和条件加载。
load
标题为“load”的部分类型: (context: LoaderContext) => Promise<void>
一个在构建时被调用以加载数据并更新存储的异步函数。有关更多信息,请参阅 LoaderContext
。
schema
标题为“schema”的部分类型: ZodSchema | Promise<ZodSchema> | (() => ZodSchema | Promise<ZodSchema>)
一个可选的 Zod 模式,用于定义条目的形状。它既用于验证数据,也用于为集合生成 TypeScript 类型。
如果提供了一个函数,它将在构建时在 load()
之前被调用以生成模式。你可以使用它根据配置选项或通过内省 API 来动态生成模式。
LoaderContext
标题为“LoaderContext”的部分此对象被传递给加载器的 load()
方法,并包含以下属性
collection
标题为“collection”的部分类型: string
集合的唯一名称。这是 src/content.config.ts
文件中 collections
对象的键。
store
标题为“store”的部分类型: DataStore
用于存储实际数据的数据库。使用它来用新条目更新存储。有关更多信息,请参阅 DataStore
。
meta
标题为“meta”的部分类型: MetaStore
一个作用于集合的键值存储,专为同步令牌和最后修改时间等内容设计。此元数据与集合数据一起在构建之间持久化,但仅在加载器内部可用。
const lastModified = meta.get("lastModified");// ...meta.set("lastModified", new Date().toISOString());
logger
标题为“logger”的部分一个可用于向控制台记录消息的日志记录器。请使用它代替 console.log
,以获得更有帮助的日志,日志消息中会包含加载器名称。有关更多信息,请参阅 AstroIntegrationLogger
。
config
标题为“config”的部分类型: AstroConfig
完整的、已解析的 Astro 配置对象,已应用所有默认值。有关更多信息,请参阅配置参考。
parseData
标题为“parseData”的部分类型: (props: ParseDataOptions<TData>) => Promise<TData>
根据集合模式验证和解析数据。将数据传递给此函数以在将其存储到数据存储之前进行验证和解析。
import type { Loader } from "astro/loaders";import { loadFeed } from "./feed.js";
export function feedLoader({ url }): Loader { 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 data = await parseData({ id: item.guid, data: item, }); store.set({ id, data, }); } }, };}
renderMarkdown
标题为“renderMarkdown”的部分类型: (markdown: string) => Promise<RenderedContent>
astro@5.9.0
将 Markdown 字符串渲染为 HTML,返回一个 RenderedContent
对象。
这允许你在加载器中直接渲染 Markdown 内容,使用与 Astro 内置的 glob
加载器相同的 Markdown 处理方式,并提供对渲染正文内容的 render()
函数和 <Content />
组件的访问。
将此对象分配给 DataEntry 对象的 rendered 字段,以允许用户在页面中渲染内容。
import type { Loader } from 'astro/loaders';import { loadFromCMS } from './cms.js';
export function myLoader(settings): Loader { 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, // Assume each entry has a 'content' field with markdown content rendered: await renderMarkdown(entry.content), }); } }, };}
generateDigest
标题为“generateDigest”的部分类型: (data: Record<string, unknown> | string) => string
生成一个对象或字符串的非加密内容摘要。这可以通过设置条目的digest
字段来跟踪数据是否已更改。
import type { Loader } from "astro/loaders";import { loadFeed } from "./feed.js";
export function feedLoader({ url }): Loader { 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 data = await parseData({ id: item.guid, data: item, });
const digest = generateDigest(data);
store.set({ id, data, digest, }); } }, };}
watcher
标题为“watcher”的部分类型: FSWatcher
在开发模式下运行时,这是一个文件系统监视器,可用于触发更新。有关更多信息,请参阅 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); } }); },};
refreshContextData
标题为“refreshContextData”的部分类型: Record<string, unknown>
如果加载器是由一个集成触发的,这可能会选择性地包含该集成设置的额外数据。它仅在加载器由集成触发时设置。有关更多信息,请参阅 astro:server:setup
钩子参考。
export function myLoader(options: { url: string }): Loader { return { name: "my-loader", load: async ({ refreshContextData, store, logger }) => { if(refreshContextData?.webhookBody) { logger.info("Webhook triggered with body"); processWebhook(store, refreshContextData.webhookBody); } // ... }, };}
DataStore
标题为“DataStore”的部分数据存储是加载器与内容集合数据交互的接口。它是一个键值(KV)存储,作用域限定于集合,因此加载器只能访问其自己集合的数据。
get
标题为“get”的部分类型: (key: string) => DataEntry | undefined
通过其 ID 从存储中获取一个条目。如果条目不存在,则返回 undefined
。
const existingEntry = store.get("my-entry");
返回的对象是一个 DataEntry
对象。
set
标题为“set”的部分类型: (entry: DataEntry) => boolean
在数据经过验证和解析后用于向存储中添加条目,如果条目被设置,则返回 true
。当 digest
属性确定条目未更改且不应更新时,此方法返回 false
。
for (const item of feed.items) { const data = await parseData({ id: item.guid, data: item, }); const digest = generateDigest(data); store.set({ id, data, rendered: { html: data.description ?? "", }, digest, }); }
entries
标题为“entries”的部分类型: () => Array<[id: string, DataEntry]>
以键值对数组的形式获取集合中的所有条目。
keys
标题为“keys”的部分类型: () => Array<string>
获取集合中所有条目的键。
values
标题为“values”的部分类型: () => Array<DataEntry>
以数组的形式获取集合中的所有条目。
delete
标题为“delete”的部分类型: (key: string) => void
通过其 ID 从存储中删除一个条目。
clear
标题为“clear”的部分类型: () => void
清除集合中的所有条目。
has
标题为“has”的部分类型: (key: string) => boolean
通过其 ID 检查存储中是否存在条目。
DataEntry
标题为“DataEntry”的部分这是存储在数据存储中的对象的类型。它具有以下属性
类型: string
条目的标识符,在集合内必须是唯一的。它用于在存储中查找条目,并且是该集合使用 getEntry
时的键。
data
标题为“data”的部分类型: Record<string, unknown>
条目的实际数据。当用户访问集合时,将根据集合模式生成 TypeScript 类型。
加载器有责任在将数据存储到数据存储之前使用 parseData
来验证和解析数据:获取或设置数据时不会进行验证。
filePath
标题为“filePath”的部分类型: string | undefined
作为此条目来源的文件的路径,相对于站点根目录。这仅适用于基于文件的加载器,并用于解析图像或其他资产等路径。
如果未设置,则模式中使用`image()` 辅助函数的任何字段都将被视为公共路径并且不会被转换。
body
标题为“body”的部分类型: string | undefined
条目的原始正文(如果适用)。如果条目包含已渲染内容,则此字段可用于存储原始来源。这是可选的,并且内部不使用。
digest
标题为“digest”的部分类型: string | undefined
条目的可选内容摘要。这可用于检查数据是否已更改。
在设置条目时,仅当摘要与具有相同 ID 的现有条目不匹配时,条目才会更新。
摘要的格式由加载器决定,但它必须是一个在数据更改时会更改的字符串。这可以通过 generateDigest
函数来完成。
rendered
标题为“rendered”的部分类型: RenderedContent | undefined
如果条目已渲染为 HTML,则存储包含其已渲染内容和元数据的对象。例如,这可用于存储 Markdown 条目的已渲染内容,或来自 CMS 的 HTML。
如果提供了此字段,则`render()` 函数和 `
RenderedContent
对象的格式是
{ /** Rendered HTML string. If present then `render(entry)` will return a component that renders this HTML. */ html: string; metadata?: { /** Any images that are present in this entry. Relative to the DataEntry filePath. */ imagePaths?: Array<string>; /** Any headings that are present in this file. Returned as `headings` from `render()` */ headings?: MarkdownHeading[]; /** Raw frontmatter, parsed from the file. This may include data from remark plugins. */ frontmatter?: Record<string, any>; /** Any other metadata that is present in this file. */ [key: string]: unknown; };}
如果条目包含 Markdown 内容,则可以使用 renderMarkdown()
函数从 Markdown 字符串生成此对象。