Caricamento dati
Esporta una funzione data() e il suo risultato comparirà come ctx.data nella tua funzione di render. Gira in fase di build, e a ogni richiesta nel server di sviluppo.
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
Stai costruendo molte pagine contro la stessa API? Importa fetchWithCache da sitelo:
import { fetchWithCache } from 'sitelo'
export async function data({ params }) {
const res = await fetchWithCache(
`https://api.example.com/posts/${params.slug}`,
{ /* opzioni fetch standard */ },
{ maxAge: 3600 }
)
return { post: await res.json() }
}Opzioni
maxAge— TTL della cache in secondi (predefinito3600)cacheKey— chiave personalizzata (predefinita: hash di URL + metodo + header + corpo)forceRefresh— scavalca la cachecache—'auto'|'memory'|'fs'|'none'
Modalità di cache
auto(predefinita) — memoria in sviluppo, filesystem nelle build di produzionememory— dentro al processo, svuotata quando il processo terminafs— persistita sottonode_modules/.cache/none— scarica sempre
Per impostazione predefinita vengono messe in cache solo le richieste GET (passa una cacheKey per mettere in cache altri metodi). Le risposte di errore non vengono mai messe in cache.
File JSON locali
Nessuna API? Tieni i contenuti nel repository come JSON e leggili con 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>
`I percorsi relativi si risolvono dalla radice del progetto, quindi data/posts significa la stessa cosa da qualunque punto tu esegua la CLI. readJson restituisce un file analizzato; readJsonCollection restituisce un array di voci, ciascuna con uno slug — da una cartella di file .json (uno per voce, slug dal nome del file), oppure da un singolo file che contiene un array di voci o un oggetto indicizzato per 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')Opzioni delle collezioni
slug— nome di un campo o funzione; per impostazione predefinita il nome del file, la chiave dell’oggetto, oppure loslug/iddella voce stessasort— nome di un campo ('date'crescente,'-date'decrescente) o una funzione di confrontorecursive— includi i file.jsonnelle sottocartelle, con slug ricavato dal loro percorsoroot— cartella da cui si risolvono i percorsi relativicache—'auto'|'memory'|'none'
Le letture sono memoizzate per file, quindi una build da 500 pagine analizza ogni file una volta sola. Il server di sviluppo invece rivalida rispetto a mtime, e ricarica il browser quando cambia un file JSON che una pagina ha letto. Slug duplicati, file mancanti e JSON malformato fanno fallire la build, ciascuno indicato per percorso.