Skip to content

v0.5.0

Choose a tag to compare

@D3ller D3ller released this 29 Jul 19:39

🏷️ CDN purging. Publishing left the CDN serving the previous content until cdnCacheSeconds expired. Cached responses are now tagged, so a purge can name exactly what changed.

A CDN cannot usually be purged by URL — Vercel, Cloudflare and Fastly all purge by tag — and one entry appears in more than one cached response: its own, and the listing of the collection that contains it.

Response Tags
pages/homepage eponyme, eponyme:pages/homepage
articles/my-article eponyme, eponyme:articles/my-article, eponyme:articles
The articles listing eponyme, eponyme:articles

Publishing an article therefore drops both the article page and the index that lists it.

Wiring it up

getEponymeCacheTags() is auto-imported into server code and returns exactly the tags the responses were given, so a listener cannot drift from what it is trying to purge:

// server/plugins/purge.ts
import { invalidateByTag } from '@vercel/functions'

export default defineNitroPlugin((nitroApp) => {
  const purge = async ({ name, collection }) => {
    if (!process.env.VERCEL) return
    await invalidateByTag(getEponymeCacheTags(name, collection)).catch(() => {})
  }
  nitroApp.hooks.hook('eponyme:entry:published', purge)
  nitroApp.hooks.hook('eponyme:entry:trashed', purge)
  nitroApp.hooks.hook('eponyme:entry:untrashed', purge)
})

Invalidating rather than deleting marks the entry stale and revalidates in the background, so no visitor waits on the origin. A failed purge should be swallowed: a publication that reached the database succeeded, and an unreachable CDN must not report it as an error the editor cannot act on. The content still appears when cdnCacheSeconds runs out on its own.

browserCacheSeconds remains out of reach of any purge — a visitor already holding a copy keeps it until it expires, which is why it defaults to 30 seconds.

🚀 Features

  • server: Vercel-Cache-Tag and Cache-Tag on every cacheable response
  • server: getEponymeCacheTags(), auto-imported, returning the tags a purge must invalidate

🩹 Fixes

  • server: Nothing uncacheable is tagged — there would be nothing to purge, and a tag on a no-store response only invites the belief that one exists

✅ Tests

  • The emitted tags are asserted end to end, including that a collection entry carries its collection and that a no-store route carries none

Full Changelog: v0.4.0...v0.5.0