revalidatePath
Purge the cached page at a URL path - or everything below it - from server code, so the next request renders it fresh.
ts
import { revalidatePath } from '@gio.js/core';
await revalidatePath('/blog/hello-world');
await revalidatePath('/blog', { type: 'prefix' });Reference
| Parameter | Type | Default | Description |
|---|---|---|---|
path (required) | string | - | The URL path the page is served at, starting with /. Decoded (/blog/café) and percent-encoded (/blog/caf%C3%A9) spellings purge the same page. A query string or fragment is ignored. |
options.type | 'page' | 'prefix' | 'page' | 'page': only the page at exactly this path. 'prefix': the path and every page below it, at segment boundaries - /blog covers /blog/a but not /blogger. |
Returns
A Promise<RevalidateResult>:
| Field | Type | Default | Description |
|---|---|---|---|
ok | boolean | - | True once the server confirmed the purge. |
purged | number | - | Cache entries removed. Every query-string and locale variant of a page is its own entry; 0 means nothing was cached there. |
error | string | undefined | - | Why the purge was not confirmed, when ok is false. |
Behavior
- The worker sends the purge to the Rust server over its IPC connection, and the promise resolves when the server has dropped the entries from memory and disk, partial-prerendering shells included. The next request for each page is a cache miss: nobody is served the old page while a refresh runs.
- Every variant of the page goes: all query strings and all locales. A leading locale segment in
pathis dropped, because pages are cached under their locale-free path -/fr/aboutpurges/aboutin every locale, and a bare/frprefix purges the whole site. - The path is the one the page renders at, after any rewrite rule.
- A render that was already running when the purge landed still answers the requests waiting for it, but its result is not stored: it may have read the old data.
- It never throws for a purge that could not be confirmed. After 5 seconds without the server's answer, or when the connection drops, it resolves
{ ok: false, purged: 0, error }and logs a warning, so a write that already succeeded is not failed over its cache refresh. - Calls run at most 16 at a time per worker; the rest wait their turn within the same 5 seconds, so
Promise.allover many paths is safe.
Errors
An invalid argument is a programming error: the promise rejects with a TypeError naming the path and the problem, and nothing is sent.
- The path does not start with
/, or is not a string. - It is longer than 2048 bytes, or contains a control character or an unpaired UTF-16 surrogate.
- A
%that does not start an escape (write a literal%as%25). - A
.or..segment. - A path under
/_gio, which is the server's own and never cached. typeother than'page'or'prefix'.
Examples
After an update in a route handler
app/api/posts/[id]/route.ts
import { notFound, revalidatePath, type GioRequest } from '@gio.js/core';
export async function PUT(req: GioRequest<'/api/posts/:id'>) {
const { title } = req.json<{ title: string }>();
const post = await db.posts.update(req.params.id, title);
if (post === null) notFound();
await revalidatePath(`/blog/${post.slug}`); // the post itself
await revalidatePath('/'); // the home page lists it
return post;
}After a page action
app/admin/menu/page.tsx
import { redirect, revalidatePath, type ActionArgs } from '@gio.js/core';
export async function action(req: ActionArgs) {
const form = await req.formData();
await db.menu.save(String(form.get('items')));
// Every page under /menu shows the menu.
const result = await revalidatePath('/menu', { type: 'prefix' });
if (!result.ok) console.warn('menu cache not purged:', result.error);
return redirect('/admin/menu');
}Good to know
- One server instance. The cache belongs to the server the worker runs behind. With several instances, call
POST /_gio/revalidateon each of the others (see Caching). - Outside the server -
gio export,renderPage/callRoutein unit tests - there is no cache: it resolves{ ok: false, error: 'not running behind the GioJS server' }and warns once per process. - Uncached pages need nothing. Only pages that export
revalidateare stored; a page that renders on every request is always fresh. - Many pages, one tag. When one change affects pages at unrelated paths, tag them and use revalidateTag instead of listing paths.
Related
- Caching & Revalidating
- revalidateTag
- export const revalidate
- [revalidate] - the token for
POST /_gio/revalidate
Version history
| Version | Changes |
|---|---|
v0.1.0-beta.8 | Introduced. |