跳转到内容

Astro 内容加载器 API

Astro 的内容加载器 API 允许你从任何来源(本地或远程)加载数据,并与 Astro 的内容层交互来管理你的内容集合

Astro 加载器允许你将数据加载到内容集合中,然后在页面和组件中使用。内置的 glob()file() 加载器用于从文件系统加载内容,你也可以创建自己的加载器从其他来源加载内容。

每个集合都需要在其模式中定义一个加载器。你可以在项目的 src/content.config.ts 文件中内联定义一个加载器,在多个集合之间共享一个加载器,甚至可以将你的加载器作为包发布到 NPM 与他人共享,并被收录到我们的集成库中。

Astro 提供了两个内置加载器来帮助你获取集合。两者都提供了适用于各种用例的选项。

类型: (options: GlobOptions) => Loader

添加于: astro@5.0.0

glob() 加载器从文件系统任意位置的文件目录创建条目。支持的文件类型有 Markdown、MDX、Markdoc、JSON 和 YAML 文件。

该加载器接受一个包含以下属性的对象:patternbase(可选)和 generateId(可选)。

src/content.config.ts
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: /* ... */
});

类型: string | string[]

pattern 属性接受一个使用 glob 匹配(例如通配符、globstars)的字符串或字符串数组。这些模式必须相对于要匹配的条目文件的基本目录。

你可以在 micromatch 文档中了解更多关于要使用的语法。你也可以使用像 DigitalOcean Glob Tool 这样的在线工具来验证你的模式的有效性。

类型: string | URL
默认值: "."

一个相对路径或URL,用于解析 pattern 的目录。

类型: (options: GenerateIdOptions) => string

一个回调函数,为集合中的每个条目返回一个唯一的字符串。它接受一个对象作为参数,该对象具有以下属性

  • entry - 条目文件的路径,相对于基本目录
  • base - 基本目录的 URL
  • data - 条目的已解析但未验证的数据

默认情况下,它使用 github-slugger 生成一个使用短横线命名法(kebab-cased)的 slug。

类型: (fileName: string, options?: FileOptions) => Loader

添加于: astro@5.0.0

file() 加载器从单个文件中创建条目,该文件包含一个具有唯一 id 字段的对象数组,或一个以 ID 为键、以条目为值的对象。它支持 JSON 或 YAML,对于默认无法解析的数据文件,你可以提供一个自定义的 parser

该加载器接受一个 fileName 属性和一个可选的对象作为第二个参数

src/content.config.ts
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: /* ... */
});

类型: string

设置要加载的文件的路径,相对于根目录。

类型: FileOptions

一个可选对象,具有以下属性

类型: (text: string) => Record<string, Record<string, unknown>> | Array<Record<string, unknown>>

一个从文件内容创建集合的回调函数。当你需要处理默认不支持的文件(例如 .csv)或使用嵌套的 .json 文档时,请使用它。

加载器可以定义为一个返回条目数组的简单函数,也可以使用更强大的对象内容加载器 API,以便对加载过程进行更多控制。

内联加载器是一个异步函数,返回一个包含条目的数组或对象。这适用于简单的加载器,尤其是在 src/content.config.ts 文件中内联定义的加载器。

该函数可以是异步的,并且必须返回一个条目数组(每个条目都包含一个唯一的 id 字段),或一个以唯一 ID 为键、以条目为值的对象。每当调用加载器时,它都会清除存储并重新加载所有条目。

src/content.config.ts
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 插件一样。

loader.ts
import type { Loader, LoaderContext } from 'astro/loaders';
import { z } from 'astro:content';
import { loadFeedData } from "./feed.js";
// Define any options that the loader needs
export 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({
// ...
})
};
}

然后可以在定义集合时设置这些配置选项

src/content.config.ts
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。

加载器对象具有以下属性

类型string

加载器的唯一名称,用于日志和条件加载

类型(context: LoaderContext) => Promise<void>

一个在构建时被调用以加载数据并更新存储的异步函数。有关更多信息,请参阅 LoaderContext

类型ZodSchema | Promise<ZodSchema> | (() => ZodSchema | Promise<ZodSchema>)

一个可选的 Zod 模式,用于定义条目的形状。它既用于验证数据,也用于为集合生成 TypeScript 类型。

如果提供了一个函数,它将在构建时在 load() 之前被调用以生成模式。你可以使用它根据配置选项或通过内省 API 来动态生成模式。

此对象被传递给加载器的 load() 方法,并包含以下属性

类型string

集合的唯一名称。这是 src/content.config.ts 文件中 collections 对象的键。

类型DataStore

用于存储实际数据的数据库。使用它来用新条目更新存储。有关更多信息,请参阅 DataStore

类型MetaStore

一个作用于集合的键值存储,专为同步令牌和最后修改时间等内容设计。此元数据与集合数据一起在构建之间持久化,但仅在加载器内部可用。

const lastModified = meta.get("lastModified");
// ...
meta.set("lastModified", new Date().toISOString());

类型AstroIntegrationLogger

一个可用于向控制台记录消息的日志记录器。请使用它代替 console.log,以获得更有帮助的日志,日志消息中会包含加载器名称。有关更多信息,请参阅 AstroIntegrationLogger

类型AstroConfig

完整的、已解析的 Astro 配置对象,已应用所有默认值。有关更多信息,请参阅配置参考

类型(props: ParseDataOptions<TData>) => Promise<TData>

根据集合模式验证和解析数据。将数据传递给此函数以在将其存储到数据存储之前进行验证和解析。

loader.ts
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,
});
}
},
};
}

类型(markdown: string) => Promise<RenderedContent>

添加于: astro@5.9.0

将 Markdown 字符串渲染为 HTML,返回一个 RenderedContent 对象。

这允许你在加载器中直接渲染 Markdown 内容,使用与 Astro 内置的 glob 加载器相同的 Markdown 处理方式,并提供对渲染正文内容render() 函数和 <Content /> 组件的访问。

将此对象分配给 DataEntry 对象的 rendered 字段,以允许用户在页面中渲染内容

loader.ts
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),
});
}
},
};
}

类型(data: Record<string, unknown> | string) => string

生成一个对象或字符串的非加密内容摘要。这可以通过设置条目的digest 字段来跟踪数据是否已更改。

loader.ts
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,
});
}
},
};
}

类型FSWatcher

在开发模式下运行时,这是一个文件系统监视器,可用于触发更新。有关更多信息,请参阅 ViteDevServer

从 file() 加载器中提取
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);
}
});
},
};

类型Record<string, unknown>

如果加载器是由一个集成触发的,这可能会选择性地包含该集成设置的额外数据。它仅在加载器由集成触发时设置。有关更多信息,请参阅 astro:server:setup 钩子参考。

loader.ts
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);
}
// ...
},
};
}

数据存储是加载器与内容集合数据交互的接口。它是一个键值(KV)存储,作用域限定于集合,因此加载器只能访问其自己集合的数据。

类型(key: string) => DataEntry | undefined

通过其 ID 从存储中获取一个条目。如果条目不存在,则返回 undefined

const existingEntry = store.get("my-entry");

返回的对象是一个 DataEntry 对象。

类型(entry: DataEntry) => boolean

在数据经过验证和解析后用于向存储中添加条目,如果条目被设置,则返回 true。当 digest 属性确定条目未更改且不应更新时,此方法返回 false

loader.ts
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,
});
}

类型() => Array<[id: string, DataEntry]>

以键值对数组的形式获取集合中的所有条目。

类型() => Array<string>

获取集合中所有条目的键。

类型() => Array<DataEntry>

以数组的形式获取集合中的所有条目。

类型(key: string) => void

通过其 ID 从存储中删除一个条目。

类型() => void

清除集合中的所有条目。

类型(key: string) => boolean

通过其 ID 检查存储中是否存在条目。

这是存储在数据存储中的对象的类型。它具有以下属性

类型string

条目的标识符,在集合内必须是唯一的。它用于在存储中查找条目,并且是该集合使用 getEntry 时的键。

类型Record<string, unknown>

条目的实际数据。当用户访问集合时,将根据集合模式生成 TypeScript 类型。

加载器有责任在将数据存储到数据存储之前使用 parseData 来验证和解析数据:获取或设置数据时不会进行验证。

类型string | undefined

作为此条目来源的文件的路径,相对于站点根目录。这仅适用于基于文件的加载器,并用于解析图像或其他资产等路径。

如果未设置,则模式中使用`image()` 辅助函数的任何字段都将被视为公共路径并且不会被转换。

类型string | undefined

条目的原始正文(如果适用)。如果条目包含已渲染内容,则此字段可用于存储原始来源。这是可选的,并且内部不使用。

类型string | undefined

条目的可选内容摘要。这可用于检查数据是否已更改。

设置条目时,仅当摘要与具有相同 ID 的现有条目不匹配时,条目才会更新。

摘要的格式由加载器决定,但它必须是一个在数据更改时会更改的字符串。这可以通过 generateDigest 函数来完成。

类型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 字符串生成此对象。

贡献 社区 赞助