Загрузка данных
Экспортируйте функцию data(), и её результат появится как ctx.data в вашей функции рендеринга. Она выполняется во время сборки и на каждый запрос в сервере разработки.
export async function data({ params, dev }) {
const res = await fetch(`https://api.example.com/posts/${params.slug}`)
return await res.json()
}
export default ({ data }) => `
<html><body>
<h1>${data.title}</h1>
${data.body}
</body></html>
`import { html, body, h1 } from 'javascript-to-html'
export async function data({ params, dev }) {
const res = await fetch(`https://api.example.com/posts/${params.slug}`)
return await res.json()
}
export default ({ data }) =>
html(
body(
h1(data.title),
data.body,
),
)export async function data({ params, dev }) {
const res = await fetch(`https://api.example.com/posts/${params.slug}`)
return await res.json()
}
export default function Post({ data }) {
return (
<html>
<body>
<h1>{data.title}</h1>
<div dangerouslySetInnerHTML={{ __html: data.body }} />
</body>
</html>
)
}fetchWithCache
Собираете много страниц с одного API? Импортируйте fetchWithCache из sitelo:
import { fetchWithCache } from 'sitelo'
export async function data({ params }) {
const res = await fetchWithCache(
`https://api.example.com/posts/${params.slug}`,
{ /* обычные параметры fetch */ },
{ maxAge: 3600 }
)
return { post: await res.json() }
}Параметры
maxAge— время жизни кэша в секундах (по умолчанию3600)cacheKey— свой ключ (по умолчанию: хэш URL + метода + заголовков + тела)forceRefresh— обойти кэшcache—'auto'|'memory'|'fs'|'none'
Режимы кэша
auto(по умолчанию) — память при разработке, файловая система в продакшн-сборкахmemory— в процессе, очищается при его завершенииfs— сохраняется вnode_modules/.cache/none— всегда запрашивает заново
По умолчанию кэшируются только GET-запросы (передайте cacheKey, чтобы кэшировать другие методы). Ответы с ошибками не кэшируются никогда.
Локальные JSON-файлы
Нет API? Держите контент в репозитории в виде JSON и читайте его через sitelo/data.
data/
├─ site.json
└─ posts/
├─ hello-world.json
└─ why-static.jsonimport { readJsonCollection } from 'sitelo/data'
const posts = () => readJsonCollection('data/posts', { sort: '-date' })
export async function generateStaticParams() {
return (await posts()).map((post) => ({ slug: post.slug }))
}
export async function data({ params }) {
return (await posts()).find((post) => post.slug === params.slug)
}
export default ({ data }) => `
<html><body>
<h1>${data.title}</h1>
<time datetime="${data.date}">${data.date}</time>
${data.body}
</body></html>
`Относительные пути разрешаются от корня проекта, поэтому data/posts означает одно и то же, откуда бы вы ни запускали CLI. readJson возвращает один разобранный файл; readJsonCollection возвращает массив записей, у каждой есть slug — из каталога .json-файлов (по файлу на запись, slug из имени файла) или из одного файла с массивом записей либо объектом, ключи которого — слаги.
// data/posts/hello-world.json -> { slug: 'hello-world', ... }
await readJsonCollection('data/posts')
// data/posts.json: [{ "slug": "hello-world", ... }]
// data/posts.json: { "hello-world": { ... } }
await readJsonCollection('data/posts.json')
// data/site.json
await readJson('data/site.json')Параметры коллекции
slug— имя поля или функция; по умолчанию имя файла, ключ объекта или собственныйslug/idзаписиsort— имя поля ('date'по возрастанию,'-date'по убыванию) или функция сравненияrecursive— включать.json-файлы из подкаталогов, slug берётся из путиroot— каталог, от которого разрешаются относительные путиcache—'auto'|'memory'|'none'
Чтение запоминается по файлу, поэтому сборка из 500 страниц разбирает каждый файл один раз. Dev-сервер вместо этого сверяет mtime и перезагружает страницу, когда меняется прочитанный JSON-файл. Повторяющиеся слаги, отсутствующие файлы и некорректный JSON останавливают сборку — с указанием пути.