Revalidación de paths — revalidatePath()
revalidate (el de fetching con revalidate) refresca por tiempo. revalidatePath refresca al instante, bajo demanda — el caso típico es “acabo de guardar algo, quiero que la página que lo lista se actualice ya, no en N segundos”.
Uso básico
Sección titulada «Uso básico»Se llama desde un Server Action o un Route Handler — nunca desde un Client Component ni desde el Proxy, porque solo funciona en el servidor.
"use server"
import { revalidatePath } from "next/cache"
export async function crearPost(formData: FormData) { await guardarPost(formData) revalidatePath("/posts")}Un path literal vs un patrón de ruta
Sección titulada «Un path literal vs un patrón de ruta»Un path literal (/blog/mi-post) invalida esa página puntual. Para invalidar todas las páginas que matchean una ruta dinámica, se usa el patrón con [slug] más el segundo argumento 'page' (obligatorio en ese caso).
revalidatePath("/blog/mi-post") // solo esa páginarevalidatePath("/blog/[slug]", "page") // todas las que usan ese page.tsxrevalidatePath("/blog/[slug]", "layout") // esas más todo lo anidado debajo del layoutrevalidatePath("/", "layout") // toda la apprevalidateTag — La alternativa por etiqueta
Sección titulada «revalidateTag — La alternativa por etiqueta»Mientras revalidatePath invalida por ruta, revalidateTag invalida por etiqueta — todos los fetches en cualquier página que hayan usado esa tag (ver next.tags en fetching con revalidate), sin importar en qué ruta estén.
"use server"
import { revalidateTag } from "next/cache"
export async function actualizarPost(id: string) { await guardarCambios(id) revalidateTag("posts") // invalida CUALQUIER fetch etiquetado "posts", en cualquier página}La diferencia importa en la práctica: si /blog y /dashboard piden datos distintos pero ambos etiquetados posts, revalidatePath('/blog') deja /dashboard con datos viejos — revalidateTag('posts') actualiza ambos.
Combinarlos
Sección titulada «Combinarlos»No son excluyentes — una mutación que afecta tanto una página puntual como datos compartidos por tag puede llamar a los dos.
"use server"
import { revalidatePath, revalidateTag } from "next/cache"
export async function actualizarPost(id: string) { await guardarCambios(id) revalidatePath("/blog") // refresca esa página ya revalidateTag("posts") // refresca cualquier otra página que use esos datos}Estrategias de invalidación en una mirada
Sección titulada «Estrategias de invalidación en una mirada»| Función | Invalida por | Alcance |
|---|---|---|
revalidatePath(path) | Ruta específica | Esa página (o layout + todo lo anidado, con 'layout') |
revalidatePath(patron, 'page') | Patrón de ruta dinámica | Todas las páginas que matchean ese page.tsx |
revalidateTag(tag) | Etiqueta de datos | Cualquier página que use un fetch con esa tag, sin importar la ruta |
Consistencia, alcance y errores
Sección titulada «Consistencia, alcance y errores»- Con
rewritesconfigurados ennext.config,revalidatePathnecesita el path de destino (la ubicación real del archivo de ruta), no el que el usuario ve en la URL — son distintos cuando hay un rewrite de por medio. - Llamado desde un Server Action, actualiza la UI en la misma respuesta si estás viendo esa ruta ahora mismo. Llamado desde un Route Handler, solo marca la ruta para revalidar en la próxima visita — no dispara nada de inmediato.
- Ninguna de las dos funciona en Client Components ni en
proxy.ts— ambas son server-only, por diseño (necesitan tocar la caché del servidor directamente).