Guides
Caching
Keep the pages of your site at the edge, and purge exactly what changed when you publish, edit or unpublish, in seconds.
Caching
A page that reads Hollware does not have to be rendered for every reader. Hollware knows exactly what changed when you publish, edit or unpublish an entry, so your site keeps its pages at the edge and purges only those that showed it. Most requests then run nothing at all, and a change shows in seconds everywhere.
With Nuxt
Turn it on in nuxt.config.ts:
export default defineNuxtConfig({
modules: ['@hollware/nuxt'],
hollware: { site: 'my-site', cache: 'purge' },
})and give the site's Worker its cache in wrangler.jsonc:
{
"cache": { "enabled": true },
}Each page is then kept by Cloudflare's Workers Cache, which serves it without running your Worker, tagged with what it showed. Errors, writes and pages that read nothing are never kept, and the browser keeps nothing: only the edge does.
Then tell Hollware where to send its events. In the admin, under Site, add a webhook named site with the URL https://your-site.example/_hollware/webhook. Hollware makes its secret and shows it once: set it on the site's Worker.
npx wrangler secret put NUXT_HOLLWARE_WEBHOOK_SECRETFrom then on, every publish, edit and unpublish purges the pages that showed that entry, its lists and the pages that link to its translations, and a change of the site's structure (a collection, a route, a locale) purges the pages that show the structure and every list. On hollware.com, a published page shows about eight seconds after it is approved.
cache: 30 instead keeps each page 30 seconds in every isolate, with no webhook: simpler, and a change shows within that time.The contract, for any other stack
Every event Hollware sends carries cacheTags, the tags the change invalidates:
{
"kind": "entry.published",
"entry": { "id": "ent_01JAB3XQ8ZK4M6N2P5R7S9T0VW", "collection": "blog", "locale": "en", "slug": "hello-world" },
"path": "/blog/hello-world/",
"cacheTags": ["entry:ent_01JAB3XQ8ZK4M6N2P5R7S9T0VW", "list:blog:en", "list:blog:*", "group:blog:hello-world"]
}A change of the site's structure sends site.changed, which carries no entry, only the tags: site, and the lists of every collection in every locale the site had or has.
Tag each page with what it shows, in the same names, and purge the tags of each event:
| Tag | A page that |
|---|---|
entry:<id> | shows the entry, alone or among others |
list:<collection>:<locale> | lists the entries of a collection in a locale |
list:<collection>:* | lists them in every locale |
group:<collection>:<group> | links to the translations of a group |
site | shows the structure of the site, such as its navigation |
@hollware/core exports the functions that make them: entryTag, listTag, groupTag, tagsOfChange and tagsOfSiteChange. Check each event's signature with verifyWebhook before you purge anything.
import { parseHollwareEvent, verifyWebhook } from '@hollware/core'
const body = await request.text()
const ok = await verifyWebhook({
secret: env.HOLLWARE_WEBHOOK_SECRET,
body,
headers: request.headers,
// Refuses an event it was given before, by the id in the signed body: a captured request
// sent again within the five minutes of tolerance is refused too. Keep each id for a day.
isNew: async (id) => {
if ((await env.SEEN.get(id)) !== null) return false
await env.SEEN.put(id, '1', { expirationTtl: 86_400 })
return true
},
})
if (!ok) return new Response(null, { status: 401 })
const event = parseHollwareEvent(JSON.parse(body))verifyWebhook alone, without the rest of @hollware/core, is in @hollware/client/webhooks, which imports nothing: a site on another major version of zod checks its deliveries with it.
A retry of a delivery carries the same id: if your receiver can fail after isNew has recorded an id, record it only once the event is handled, so the retry is not refused.