You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
vitepress/docs/ru/guide/data-loading.md

259 lines
12 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# Загрузка данных в режиме реального времени {#build-time-data-loading}
VitePress предоставляет функцию **загрузчиков данных**, которая позволяет загружать произвольные данные и импортировать их со страниц или компонентов. Загрузка данных выполняется **только во время сборки**: Полученные данные будут сериализованы в виде JSON в финальной сборке JavaScript.
Загрузчики данных могут использоваться для получения удалённых данных или генерирования метаданных на основе локальных файлов. Например, вы можете использовать загрузчики данных для анализа всех локальных страниц API и автоматического создания индекса всех записей API.
## Пример использования {#basic-usage}
Файл загрузчика данных должен заканчиваться либо `.data.js`, либо `.data.ts`. Файл должен предоставлять экспорт объекта по умолчанию с помощью метода `load()`:
```js
// example.data.js
export default {
load() {
return {
hello: 'мир'
}
}
}
```
Модуль загрузчика выполняется только в Node.js, поэтому вы можете импортировать любые API Node и зависимости npm по мере необходимости.
Затем вы можете импортировать данные из этого файла в страницы `.md` и компоненты `.vue` с помощью экспорта с именем `data`:
```vue
<script setup>
import { data } from './example.data.js'
</script>
<pre>{{ data }}</pre>
```
Результат:
```json
{
"hello": "мир"
}
```
Вы заметите, что сам загрузчик данных не экспортирует `data`. Это VitePress вызывает метод `load()` за кулисами и неявно раскрывает результат через именованный экспорт `data`.
Это работает, даже если загрузчик асинхронный:
```js
export default {
async load() {
// получение удалённых данных
return (await fetch('...')).json()
}
}
```
## Данные из локальных файлов {#data-from-local-files}
Если вам нужно генерировать данные на основе локальных файлов, используйте опцию `watch` в загрузчике данных, чтобы изменения, внесённые в эти файлы, вызывали горячие обновления.
Опция `watch` удобна ещё и тем, что вы можете использовать [шаблоны glob](https://github.com/mrmlnc/fast-glob#pattern-syntax) для соответствия нескольким файлам. Шаблоны могут быть относительными к самому файлу загрузчика, а функция `load()` будет получать совпадающие файлы в виде абсолютных путей.
В следующем примере показана загрузка CSV-файлов и их преобразование в JSON с помощью [csv-parse](https://github.com/adaltas/node-csv/tree/master/packages/csv-parse/). Поскольку этот файл выполняется только во время сборки, вы не будете передавать CSV-парсер клиенту!
```js
import fs from 'node:fs'
import { parse } from 'csv-parse/sync'
export default {
watch: ['./data/*.csv'],
load(watchedFiles) {
// watchedFiles будет представлять собой массив абсолютных путей к найденным файлам.
// Формируем массив метаданных записи блога, которые можно использовать для визуализации списка в макете темы
return watchedFiles.map((file) => {
return parse(fs.readFileSync(file, 'utf-8'), {
columns: true,
skip_empty_lines: true
})
})
}
}
```
## `createContentLoader` {#createcontentloader}
При создании сайта, ориентированного на контент, нам часто приходится создавать страницы типа «архив», или «индекс», на которых мы перечисляем все доступные записи в нашей коллекции контента. Например, записи в блоге или страницы API. Мы **можем** реализовать это напрямую с помощью API загрузчика данных, но поскольку это очень распространённый случай использования, VitePress также предоставляет функцию `createContentLoader`, чтобы упростить эту задачу:
```js
// posts.data.js
import { createContentLoader } from 'vitepress'
export default createContentLoader('posts/*.md' /* параметры */)
```
Эта функция принимает шаблон glob относительно [исходного каталога](./routing#source-directory) и возвращает объект `{ watch, load }` загрузчика данных, который может быть использован в качестве экспорта по умолчанию в файле загрузчика данных. В нем также реализовано кэширование на основе временных меток изменения файлов для повышения производительности dev.
Обратите внимание, что загрузчик работает только с файлами Markdown — совпадающие файлы, не относящиеся к Markdown, будут пропущены.
Загруженные данные будут представлять собой массив с типом `ContentData[]`:
```ts
interface ContentData {
// отображаемый URL-адрес страницы, например: /posts/hello.html (не включает `base`)
// выполните итерацию вручную или используйте пользовательскую `трансформацию` для нормализации путей
url: string
// метаданные страницы
frontmatter: Record<string, any>
// следующие параметры присутствуют только в том случае, если соответствующие опции включены
// мы рассмотрим их ниже
src: string | undefined
html: string | undefined
excerpt: string | undefined
}
```
По умолчанию указываются только `url` и `frontmatter`. Это связано с тем, что загруженные данные будут вложены в клиентский пакет в виде JSON, поэтому нам нужно быть осторожными с их размером. Вот пример использования этих данных для создания минимальной индексной страницы блога:
```vue
<script setup>
import { data as posts } from './posts.data.js'
</script>
<template>
<h1>Все записи блога</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>
```
### Параметры {#options}
Данные по умолчанию могут не соответствовать всем требованиям — вы можете изменить данные с помощью параметров:
```js
// posts.data.js
import { createContentLoader } from 'vitepress'
export default createContentLoader('posts/*.md', {
includeSrc: true, // включить исходный текст в формате Markdown?
render: true, // включать в себя полный HTML страницы?
excerpt: true, // включить отрывок?
transform(rawData) {
// составляйте карты, сортируйте или фильтруйте исходные данные по своему усмотрению.
// конечный результат — это то, что будет отправлено клиенту.
return rawData
.sort((a, b) => {
return +new Date(b.frontmatter.date) - +new Date(a.frontmatter.date)
})
.map((page) => {
page.src // исходный текст в формате Markdown
page.html // отображение полной страницы HTML
page.excerpt // отображаемый отрывок HTML (содержимое выше первого `---`)
return {
/* ... */
}
})
}
})
```
Посмотрите, как он используется в [блоге Vue.js](https://github.com/vuejs/blog/blob/main/.vitepress/theme/posts.data.ts).
API `createContentLoader` также можно использовать внутри [хуков сборки](../reference/site-config#build-hooks):
```js
// .vitepress/config.js
export default {
async buildEnd() {
const posts = await createContentLoader('posts/*.md').load()
// генерируем файлы на основе метаданных сообщений, например, RSS-канал
}
}
```
**Types**
```ts
interface ContentOptions<T = ContentData[]> {
/**
* Включаем src?
* @default false
*/
includeSrc?: boolean
/**
* Преобразовываем src в HTML и включаем в данные?
* @default false
*/
render?: boolean
/**
* Если `boolean`, то следует ли разбирать и включать отрывок? (отображается как HTML)
*
* Если `function`, то управляйте тем, как отрывок извлекается из содержимого.
*
* Если `string`, определите пользовательский разделитель, который будет использоваться для извлечения
* отрывка. Разделителем по умолчанию является `---`, если `excerpt` имеет значение `true`.
*
* @see https://github.com/jonschlinkert/gray-matter#optionsexcerpt
* @see https://github.com/jonschlinkert/gray-matter#optionsexcerpt_separator
*
* @default false
*/
excerpt?:
| boolean
| ((
file: {
data: { [key: string]: any }
content: string
excerpt?: string
},
options?: any
) => void)
| string
/**
* Преобразуйте данные. Обратите внимание, что при импорте из компонентов или файлов
* с разметкой данные будут вложены в клиентский пакет в виде JSON.
*/
transform?: (data: ContentData[]) => T | Promise<T>
}
```
## Загрузчики типизированных данных {#typed-data-loaders}
При использовании TypeScript вы можете ввести свой загрузчик и экспортировать `data` следующим образом:
```ts
import { defineLoader } from 'vitepress'
export interface Data {
// тип данных
}
declare const data: Data
export { data }
export default defineLoader({
// тип проверенных опций загрузчика
watch: ['...'],
async load(): Promise<Data> {
// ...
}
})
```
## Конфигурация {#configuration}
Чтобы получить информацию о конфигурации внутри загрузчика, вы можете использовать код, подобный этому:
```ts
import type { SiteConfig } from 'vitepress'
const config: SiteConfig = (globalThis as any).VITEPRESS_CONFIG
```