GioJSdocs
On this page

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

ParameterTypeDefaultDescription
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>:

FieldTypeDefaultDescription
okboolean-True once the server confirmed the purge.
purgednumber-Cache entries removed. Every query-string and locale variant of a page is its own entry; 0 means nothing was cached there.
errorstring | 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 path is dropped, because pages are cached under their locale-free path - /fr/about purges /about in every locale, and a bare /fr prefix 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.all over 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.
  • type other 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/revalidate on each of the others (see Caching).
  • Outside the server - gio export, renderPage/callRoute in 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 revalidate are 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.

Version history

VersionChanges
v0.1.0-beta.8Introduced.