v0.5.0
🏷️ 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-TagandCache-Tagon 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-storeresponse 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-storeroute carries none
Full Changelog: v0.4.0...v0.5.0