GioJSdocs
On this page

tags

Label the cached renders of a page, so revalidateTag() can purge every page that shows some data.

app/posts/page.tsx
export const revalidate = 3600;
export const tags = ['posts'];          // await revalidateTag('posts') purges this page

Reference

OptionTypeDefaultDescription
tagsreadonly string[][]Cache tags stored with every cached render of the page. getServerSideProps can add more per render by returning { props, tags }.

Rules

  • A tag is a non-empty string of at most 256 bytes (UTF-8), without control characters, and well-formed Unicode (no unpaired surrogate).
  • Tags starting with _gio: are reserved for the server's own per-path tag.
  • A render keeps at most 64 tags: the static ones first, then those getServerSideProps returned. Duplicates are dropped.
  • An invalid tag, a tags value that is not an array, or a tag past the 64th is ignored with a warning (once per route and problem), such as cache tags ignored: export const tags: tags must not be empty. The page still renders and is still cached, with its valid tags.

Behavior

  • Tags are stored only with a render the server caches: a page with revalidate whose render is shareable. On an uncached page they are not read at all.
  • revalidateTag(tag) from server code, or POST /_gio/revalidate with { "tags": [...] }, purges every cached entry carrying the tag - every query string and locale variant, from memory and disk, PPR shells included. The next request renders fresh.
  • Every cached page can also be purged by its path with revalidatePath(), with no tag at all.

Examples

Tags from the data a render used

app/posts/[id]/page.tsx
import { notFound, type GetServerSideProps, type InferPageProps } from '@gio.js/core';
import { db, type Post } from '../../../lib/db.server.ts';

export const revalidate = 3600;
export const tags = ['posts'];

export const getServerSideProps: GetServerSideProps<{ post: Post }, '/posts/:id'> = async (ctx) => {
  const post = await db.posts.find(ctx.params.id);
  if (post === null) notFound();
  return { props: { post }, tags: [`post:${post.id}`, `author:${post.authorId}`] };
};

export default function PostPage({ post }: InferPageProps<typeof getServerSideProps>) {
  return <article><h1>{post.title}</h1><p>{post.body}</p></article>;
}

Purge after a write

app/api/posts/[id]/route.ts
import { revalidateTag, type RouteHandler } from '@gio.js/core';
import { db } from '../../../../lib/db.server.ts';

export const PUT: RouteHandler<'/api/posts/:id'> = async (req) => {
  const post = await db.posts.update(req.params.id, req.json());
  await revalidateTag(`post:${post.id}`);       // this post's page
  await revalidateTag(`author:${post.authorId}`); // pages listing the author's posts
  return post;
};

Good to know

  • Name tags after data, not pages (post:42, author:ada): one write can then purge every page that showed it.
  • revalidateTag() with an invalid tag rejects with a TypeError; an invalid tag a page declares is only a warning.
  • Purges reach the server instance whose worker runs them. With several instances, call POST /_gio/revalidate on each.
  • tags is read from page.tsx only.

Version history

VersionChanges
v0.1.0-beta.8Introduced.