构建时数据加载
VitePress 提供了一个名为 数据加载器 的功能,允许您加载任意数据并从页面或组件导入。数据加载仅在构建时执行:结果数据将在最终的 JavaScript 包中序列化为 JSON。
数据加载器可用于获取远程数据,或基于本地文件生成元数据。例如,您可以使用数据加载器来解析所有本地 API 页面并自动生成所有 API 条目的索引。
基本用法
数据加载器文件必须以.data.js或.data.ts结尾。该文件应使用load()方法提供对象的默认导出:
// example.data.js
export default {
load() {
return {
data: 'hello'
}
}
}加载器模块仅在 Node.js 中进行评估,因此您可以根据需要导入 Node API 和 npm 依赖项。
然后,您可以使用名为导出的data从该文件导入.md页面和.vue组件中的数据:
<script setup>
import { data } from './example.data.js'
</script>
<pre>{{ data }}</pre>输出:
{
"data": "hello"
}您会注意到数据加载器本身并不导出data。是 VitePress 在后台调用 load() 方法,并通过名为导出的 data 隐式暴露结果。
即使加载程序是异步的,这也有效:
export default {
async load() {
// fetch remote data
return (await fetch('...')).json()
}
}来自本地文件的数据
当需要根据本地文件生成数据时,应该使用数据加载器中的watch选项,以便对这些文件所做的更改可以触发热更新。
watch 选项也很方便,因为您可以使用 glob 模式 来匹配多个文件。这些模式可以相对于加载器文件本身,并且load()函数将接收匹配的文件作为绝对路径。
以下示例显示了加载 CSV 文件并使用 csv-parse 将其转换为 JSON。因为该文件仅在构建时执行,所以您不会将 CSV 解析器传送到客户端!
import fs from 'node:fs'
import { parse } from 'csv-parse/sync'
export default {
watch: ['./data/*.csv'],
load(watchedFiles) {
// watchedFiles will be an array of absolute paths of the matched files.
// generate an array of blog post metadata that can be used to render
// a list in the theme layout
return watchedFiles.map(file => {
return parse(fs.readFileSync(file, 'utf-8'), {
columns: true,
skip_empty_lines: true
})
})
}
}createContentLoader
在构建以内容为中心的网站时,我们通常需要创建一个"存档"或"索引"页面:在该页面中列出内容集合中的所有可用条目,例如博客文章或 API 页面。我们可以直接使用数据加载器 API 来实现这一点,但由于这是一个常见的用例,VitePress 还提供了一个 createContentLoader 帮助器来简化这一点:
// posts.data.js
import { createContentLoader } from 'vitepress'
export default createContentLoader('posts/*.md', /* options */)该帮助器采用相对于 project root 的 glob 模式,并返回一个 { watch, load } 数据加载器对象,该对象可用作数据加载器文件中的默认导出。它还根据文件修改时间戳实现缓存,以提高开发性能。
请注意,加载程序仅适用于 Markdown 文件 - 匹配的非 Markdown 文件将被跳过。
加载的数据将是一个类型为ContentData[]的数组:
interface ContentData {
// mapped absolute URL for the page. e.g. /posts/hello.html
url: string
// frontmatter data of the page
frontmatter: Record<string, any>
// the following are only present if relevant options are enabled
// we will discuss them below
src: string | undefined
html: string | undefined
excerpt: string | undefined
}默认情况下,仅提供url和frontmatter。这是因为加载的数据将作为 JSON 内联到客户端包中,因此我们需要谨慎对待其大小。以下是使用数据构建最小博客索引页面的示例:
<script setup>
import { data as posts } from './posts.data.js'
</script>
<template>
<h1>All Blog Posts</h1>
<ul>
<li v-for="post of posts">
<a :href="post.url">{{ post.frontmatter.title }}</a>
<span>by {{ post.frontmatter.author }}</span>
</li>
</ul>
</template>选项
默认数据可能无法满足所有需求 - 您可以选择使用选项来转换数据:
// posts.data.js
import { createContentLoader } from 'vitepress'
export default createContentLoader('posts/*.md', {
includeSrc: true, // include raw markdown source?
render: true, // include rendered full page HTML?
excerpt: true, // include excerpt?
transform(rawData) {
// map, sort, or filter the raw data as you wish.
// the final result is what will be shipped to the client.
return rawData.sort((a, b) => {
return +new Date(b.frontmatter.date) - +new Date(a.frontmatter.date)
}).map(page => {
page.src // raw markdown source
page.html // rendered full page HTML
page.excerpt // rendered excerpt HTML (content above first `---`)
return {/* ... */}
})
}
})查看它在Vue.js博客中的使用方式。
createContentLoader API 也可以在 build hooks 中使用:
// .vitepress/config.js
export default {
async buildEnd() {
const posts = await createContentLoader('posts/*.md').load()
// generate files based on posts metadata, e.g. RSS feed
}
}类型化数据加载器
使用 TypeScript 时,您可以输入加载程序并导出data,如下所示:
import { defineLoader } from 'vitepress'
export interface Data {
// data type
}
declare const data: Data
export { data }
export default defineLoader({
// type checked loader options
glob: ['...'],
async load(): Promise<Data> {
// ...
}
})配置
要获取加载器内部的配置信息,您可以使用如下代码:
import type { SiteConfig } from 'vitepress'
const config: SiteConfig = (globalThis as any).VITEPRESS_CONFIG