Ir al contenido
angel.library

Fetching con revalidate — las constantes de caché

Esto describe el modelo de caché “clásico” de Next (el que tiene la mayoría de los proyectos hoy). Next 16 introdujo un modelo nuevo opt-in (“Cache Components”, con la directiva use cache — ver Directivas) que reemplaza esto a futuro, pero mientras no actives cacheComponents: true en next.config, es este modelo el que aplica.

Por defecto, fetch no cachea nada. Se cachea explícitamente por request con el option cache.

await fetch("https://api.ejemplo.com/posts", { cache: "force-cache" }) // cachea indefinidamente
await fetch("https://api.ejemplo.com/posts", { cache: "no-store" }) // nunca cachea, siempre fresco

Cachea el resultado, pero lo refresca automáticamente después de N segundos (Incremental Static Regeneration a nivel de request individual).

await fetch("https://api.ejemplo.com/posts", { next: { revalidate: 3600 } }) // se refresca cada hora

next.tags — Etiquetar para invalidar bajo demanda

Sección titulada «next.tags — Etiquetar para invalidar bajo demanda»

Marca el resultado con una o más etiquetas, para poder invalidarlo manualmente después con revalidateTag (ver Revalidación de paths) — sin esperar a que venza el tiempo de revalidate.

await fetch("https://api.ejemplo.com/posts", { next: { tags: ["posts"] } })

Las constantes exportadas — a nivel de página/layout/route

Sección titulada «Las constantes exportadas — a nivel de página/layout/route»

Estas van en page.tsx, layout.tsx o route.ts, y controlan el comportamiento por defecto de todos los fetches de ese segmento que no especifican su propio cache.

Fuerza el modo de renderizado de todo el segmento.

export const dynamic = "auto"
// 'auto' (default) | 'force-dynamic' | 'error' | 'force-static'
  • 'auto': default, cachea lo que pueda sin forzar nada.
  • 'force-dynamic': siempre renderiza por request, para cada usuario — equivalente a poner cache: 'no-store' en todos los fetches del segmento.
  • 'error': fuerza estático, y tira error en build si algo del segmento usa una API que solo existe en request-time (como leer cookies) — útil para garantizar que una ruta se mantenga estática a propósito.
  • 'force-static': fuerza estático, pero en vez de error, hace que cookies()/headers()/useSearchParams() devuelvan valores vacíos en vez de fallar.

El tiempo de revalidación por defecto de ese segmento — no pisa un revalidate puesto en un fetch individual, solo aplica donde ese fetch no especificó el suyo.

export const revalidate = 3600 // segundos
// false (default, cachea indefinidamente lo que se pueda) | 0 (siempre dinámico) | número

Si una ruta tiene varios segmentos (layout + page) con distinto revalidate, gana el menor de todos — así una página nunca queda “más fresca” que lo que su layout permite.

Opción avanzada: cambia el comportamiento por defecto de todos los fetches del segmento, incluso los que no pusieron ningún cache explícito. Rara vez hace falta tocarla — 'auto' (el default) ya hace lo razonable en la mayoría de los casos.

Constante / opciónNivelQué controla
fetch(url, { cache })Por request'force-cache' (cachear) vs 'no-store' (nunca)
fetch(url, { next: { revalidate } })Por requestSegundos hasta refrescar ese fetch puntual
fetch(url, { next: { tags } })Por requestEtiquetas para invalidar bajo demanda con revalidateTag
export const dynamicSegmento (page/layout/route)Forzar todo estático, todo dinámico, o error si no puede ser estático
export const revalidateSegmentoTiempo de revalidación por defecto del segmento entero
export const fetchCacheSegmentoOverride avanzado del comportamiento default de todos los fetches
  • En desarrollo (next dev), las páginas siempre se renderizan on-demand, nunca cacheadas — para ver el comportamiento real de caché hay que probar con next build && next start.
  • El valor de revalidate tiene que ser estáticamente analizable: revalidate = 3600 funciona, revalidate = 60 * 60 no (Next no evalúa expresiones ahí, necesita leer el literal en build).
  • Para datos que no vienen de fetch (una query directa a una base de datos, un ORM), estas opciones no aplican directamente. En el modelo clásico existe unstable_cache; al migrar a Cache Components se reemplaza por una función async con 'use cache', cacheLife() y cacheTag().