Caché en Next.js

Next.js mejora el rendimiento de tu aplicación y reduce costos almacenando en caché el trabajo de renderizado y las solicitudes de datos. Esta página ofrece un análisis detallado de los mecanismos de caché de Next.js, las APIs que puedes usar para configurarlos y cómo interactúan entre sí.

Es bueno saberlo: Esta página te ayuda a entender cómo funciona Next.js internamente, pero no es conocimiento esencial para ser productivo con Next.js. La mayoría de las heurísticas de caché de Next.js están determinadas por tu uso de API y tienen valores predeterminados para el mejor rendimiento con configuración cero o mínima.

Visión general

Aquí tienes una visión general de alto nivel de los diferentes mecanismos de caché y su propósito:

MecanismoQué almacenaDóndePropósitoDuración
Memoización de solicitudesValores de retorno de funcionesServidorReutilizar datos en un árbol de componentes ReactCiclo de vida por solicitud
Caché de datosDatosServidorAlmacenar datos entre solicitudes de usuarios y desplieguesPersistente (se puede revalidar)
Caché de ruta completaHTML y carga útil RSCServidorReducir costos de renderizado y mejorar rendimientoPersistente (se puede revalidar)
Caché del enrutadorCarga útil RSCClienteReducir solicitudes al servidor en navegaciónSesión de usuario o basado en tiempo

Por defecto, Next.js almacenará en caché tanto como sea posible para mejorar el rendimiento y reducir costos. Esto significa que las rutas se renderizan estáticamente y las solicitudes de datos se almacenan en caché a menos que optes por no hacerlo. El diagrama a continuación muestra el comportamiento de caché predeterminado: cuando una ruta se renderiza estáticamente en tiempo de compilación y cuando se visita por primera vez una ruta estática.

Diagrama que muestra el comportamiento de caché predeterminado en Next.js para los cuatro mecanismos, con HIT, MISS y SET en tiempo de compilación y cuando se visita una ruta por primera vez.

El comportamiento de caché cambia dependiendo de si la ruta se renderiza estática o dinámicamente, si los datos están cacheados o no, y si una solicitud es parte de una visita inicial o una navegación posterior. Dependiendo de tu caso de uso, puedes configurar el comportamiento de caché para rutas individuales y solicitudes de datos.

Memoización de solicitudes

React extiende la API fetch para memoizar automáticamente solicitudes que tienen la misma URL y opciones. Esto significa que puedes llamar a una función fetch para los mismos datos en múltiples lugares de un árbol de componentes React mientras solo se ejecuta una vez.

Solicitudes Fetch deduplicadas

Por ejemplo, si necesitas usar los mismos datos a lo largo de una ruta (ej. en un Layout, Page y múltiples componentes), no tienes que obtener los datos en la parte superior del árbol y luego pasar props entre componentes. En su lugar, puedes obtener los datos en los componentes que los necesitan sin preocuparte por las implicaciones de rendimiento de hacer múltiples solicitudes a través de la red para los mismos datos.

async function getItem() {
  // La función `fetch` se memoiza automáticamente y el resultado
  // se almacena en caché
  const res = await fetch('https://.../item/1')
  return res.json()
}

// Esta función se llama dos veces, pero solo se ejecuta la primera vez
const item = await getItem() // cache MISS

// La segunda llamada podría estar en cualquier parte de tu ruta
const item = await getItem() // cache HIT
async function getItem() {
  // La función `fetch` se memoiza automáticamente y el resultado
  // se almacena en caché
  const res = await fetch('https://.../item/1')
  return res.json()
}

// Esta función se llama dos veces, pero solo se ejecuta la primera vez
const item = await getItem() // cache MISS

// La segunda llamada podría estar en cualquier parte de tu ruta
const item = await getItem() // cache HIT

Cómo funciona la memoización de solicitudes

Diagrama que muestra cómo funciona la memoización de fetch durante el renderizado de React.
  • Mientras se renderiza una ruta, la primera vez que se llama a una solicitud particular, su resultado no estará en memoria y será un MISS de caché.
  • Por lo tanto, la función se ejecutará, los datos se obtendrán de la fuente externa y el resultado se almacenará en memoria.
  • Las llamadas posteriores a la función de la misma solicitud en el mismo pase de renderizado serán un HIT de caché, y los datos se devolverán de la memoria sin ejecutar la función.
  • Una vez que la ruta se ha renderizado y el pase de renderizado ha terminado, la memoria se "reinicia" y se borran todas las entradas de memoización de solicitudes.

Es bueno saberlo:

  • La memoización de solicitudes es una característica de React, no de Next.js. Se incluye aquí para mostrar cómo interactúa con otros mecanismos de caché.
  • La memoización solo se aplica al método GET en solicitudes fetch.
  • La memoización solo se aplica al árbol de componentes React, esto significa:
    • Se aplica a solicitudes fetch en generateMetadata, generateStaticParams, Layouts, Pages y otros Server Components.
    • No se aplica a solicitudes fetch en Route Handlers ya que no son parte del árbol de componentes React.
  • Para casos donde fetch no es adecuado (ej. algunos clientes de base de datos, CMS o GraphQL), puedes usar la función cache de React para memoizar funciones.

Duración

La caché dura el tiempo de vida de una solicitud al servidor hasta que el árbol de componentes React ha terminado de renderizarse.

Revalidación

Dado que la memoización no se comparte entre solicitudes al servidor y solo se aplica durante el renderizado, no es necesario revalidarla.

Optar por no usar

Para optar por no usar la memoización en solicitudes fetch, puedes pasar una signal de AbortController a la solicitud.

app/example.js
const { signal } = new AbortController()
fetch(url, { signal })

Caché de datos

Next.js tiene una Caché de datos integrada que persiste el resultado de las obtenciones de datos entre solicitudes al servidor y despliegues. Esto es posible porque Next.js extiende la API nativa fetch para permitir que cada solicitud en el servidor establezca su propia semántica de caché persistente.

Es bueno saberlo: En el navegador, la opción cache de fetch indica cómo una solicitud interactuará con la caché HTTP del navegador. En Next.js, la opción cache indica cómo una solicitud del lado del servidor interactuará con la Caché de datos del servidor.

Por defecto, las solicitudes de datos que usan fetch se almacenan en caché. Puedes usar las opciones cache y next.revalidate de fetch para configurar el comportamiento de caché.

Cómo funciona la Caché de datos

Diagrama que muestra cómo las solicitudes fetch cacheadas y no cacheadas interactúan con la Caché de datos. Las solicitudes cacheadas se almacenan en la Caché de datos y se memoizan, las solicitudes no cacheadas se obtienen de la fuente de datos, no se almacenan en la Caché de datos y se memoizan.
  • La primera vez que se llama a una solicitud fetch durante el renderizado, Next.js verifica la Caché de datos en busca de una respuesta almacenada.
  • Si se encuentra una respuesta almacenada, se devuelve inmediatamente y se memoiza.
  • Si no se encuentra una respuesta almacenada, se realiza la solicitud a la fuente de datos, el resultado se almacena en la Caché de datos y se memoiza.
  • Para datos no cacheados (ej. { cache: 'no-store' }), el resultado siempre se obtiene de la fuente de datos y se memoiza.
  • Ya sea que los datos estén cacheados o no, las solicitudes siempre se memoizan para evitar hacer solicitudes duplicadas para los mismos datos durante un pase de renderizado de React.

Diferencias entre la Caché de datos y la Memoización de solicitudes

Si bien ambos mecanismos de caché ayudan a mejorar el rendimiento reutilizando datos almacenados, la Caché de datos es persistente entre solicitudes entrantes y despliegues, mientras que la memoización solo dura el tiempo de vida de una solicitud.

Con la memoización, reducimos el número de solicitudes duplicadas en el mismo pase de renderizado que tienen que cruzar el límite de red desde el servidor de renderizado al servidor de Caché de datos (ej. una CDN o Edge Network) o fuente de datos (ej. una base de datos o CMS). Con la Caché de datos, reducimos el número de solicitudes hechas a nuestra fuente de datos original.

Duración

La Caché de datos es persistente entre solicitudes entrantes y despliegues a menos que la revalides o optes por no usarla.

Revalidación

Los datos almacenados en caché se pueden revalidar de dos maneras, con:

  • Revalidación basada en tiempo: Revalidar datos después de que haya pasado una cierta cantidad de tiempo y se haga una nueva solicitud. Esto es útil para datos que cambian con poca frecuencia y la frescura no es tan crítica.
  • Revalidación bajo demanda: Revalidar datos basados en un evento (ej. envío de un formulario). La revalidación bajo demanda puede usar un enfoque basado en etiquetas o rutas para revalidar grupos de datos a la vez. Esto es útil cuando quieres asegurarte de que se muestren los datos más recientes lo antes posible (ej. cuando se actualiza contenido de tu CMS headless).

Revalidación basada en tiempo

Para revalidar datos en intervalos de tiempo, puedes usar la opción next.revalidate de fetch para establecer el tiempo de vida de un recurso en caché (en segundos).

// Revalidar como máximo cada hora
fetch('https://...', { next: { revalidate: 3600 } })

Alternativamente, puedes usar opciones de configuración de segmento de ruta para configurar todas las solicitudes fetch en un segmento o para casos donde no puedas usar fetch.

Cómo funciona la revalidación basada en tiempo

Diagrama que muestra cómo funciona la revalidación basada en tiempo, después del período de revalidación, se devuelven datos obsoletos para la primera solicitud, luego los datos se revalidan.
  • La primera vez que se llama a una solicitud fetch con revalidate, los datos se obtendrán de la fuente de datos externa y se almacenarán en la Caché de datos.
  • Cualquier solicitud que se llame dentro del período de tiempo especificado (ej. 60 segundos) devolverá los datos almacenados.
  • Después del período de tiempo, la siguiente solicitud aún devolverá los datos almacenados (ahora obsoletos).
    • Next.js activará una revalidación de los datos en segundo plano.
    • Una vez que los datos se obtengan con éxito, Next.js actualizará la Caché de datos con los datos frescos.
    • Si la revalidación en segundo plano falla, los datos anteriores se mantendrán sin cambios.

Esto es similar al comportamiento stale-while-revalidate.

Revalidación bajo demanda

Los datos se pueden revalidar bajo demanda por ruta (revalidatePath) o por etiqueta de caché (revalidateTag).

Cómo funciona la revalidación bajo demanda

Diagrama que muestra cómo funciona la revalidación bajo demanda, la Caché de datos se actualiza con datos frescos después de una solicitud de revalidación.
  • La primera vez que se llama a una solicitud fetch, los datos se obtendrán de la fuente de datos externa y se almacenarán en la Caché de datos.
  • Cuando se activa una revalidación bajo demanda, las entradas de caché apropiadas se purgarán de la caché.
    • Esto es diferente de la revalidación basada en tiempo, que mantiene los datos obsoletos en la caché hasta que se obtienen los datos frescos.
  • La próxima vez que se haga una solicitud, será un MISS de caché nuevamente, y los datos se obtendrán de la fuente de datos externa y se almacenarán en la Caché de datos.

Optar por no usar

Para obtenciones de datos individuales, puedes optar por no usar el almacenamiento en caché configurando la opción cache en no-store. Esto significa que los datos se obtendrán cada vez que se llame a fetch.

// Optar por no usar caché para una solicitud `fetch` individual
fetch(`https://...`, { cache: 'no-store' })

Alternativamente, también puedes usar las opciones de configuración de segmento de ruta para optar por no usar caché para un segmento de ruta específico. Esto afectará todas las solicitudes de datos en el segmento de ruta, incluyendo bibliotecas de terceros.

// Optar por no usar caché para todas las solicitudes de datos en el segmento de ruta
export const dynamic = 'force-dynamic'

Caché de datos de Vercel

Si tu aplicación Next.js está desplegada en Vercel, recomendamos leer la documentación de Caché de datos de Vercel para un mejor entendimiento de las características específicas de Vercel.

Caché de ruta completa

Términos relacionados:

Puedes ver los términos Optimización estática automática, Generación de sitios estáticos o Renderizado estático usados indistintamente para referirse al proceso de renderizar y almacenar en caché rutas de tu aplicación en tiempo de compilación.

Next.js renderiza y almacena en caché rutas automáticamente en tiempo de compilación. Esta es una optimización que te permite servir la ruta almacenada en lugar de renderizar en el servidor para cada solicitud, resultando en tiempos de carga de página más rápidos.

Para entender cómo funciona la Caché de ruta completa, es útil ver cómo React maneja el renderizado y cómo Next.js almacena el resultado:

1. Renderizado de React en el servidor

En el servidor, Next.js usa las APIs de React para orquestar el renderizado. El trabajo de renderizado se divide en fragmentos: por segmentos de ruta individuales y límites de Suspense.

Cada fragmento se renderiza en dos pasos:

  1. React renderiza Server Components en un formato de datos especial optimizado para streaming, llamado React Server Component Payload.
  2. Next.js usa el React Server Component Payload y las instrucciones JavaScript de Client Components para renderizar HTML en el servidor.

Esto significa que no tenemos que esperar a que todo se renderice antes de almacenar el trabajo en caché o enviar una respuesta. En su lugar, podemos transmitir una respuesta a medida que se completa el trabajo.

¿Qué es el React Server Component Payload?

El React Server Component Payload es una representación binaria compacta del árbol de React Server Components renderizado. React lo usa en el cliente para actualizar el DOM del navegador. El React Server Component Payload contiene:

  • El resultado renderizado de Server Components
  • Marcadores de posición donde se deben renderizar Client Components y referencias a sus archivos JavaScript
  • Cualquier prop pasado de un Server Component a un Client Component

Para aprender más, consulta la documentación de Server Components.

2. Almacenamiento en caché de Next.js en el servidor (Caché de ruta completa)

Comportamiento predeterminado de la Caché de ruta completa, mostrando cómo el React Server Component Payload y el HTML se almacenan en el servidor para rutas renderizadas estáticamente.

El comportamiento predeterminado de Next.js es almacenar en caché el resultado renderizado (React Server Component Payload y HTML) de una ruta en el servidor. Esto se aplica a rutas renderizadas estáticamente en tiempo de compilación o durante la revalidación.

3. Hidratación y reconciliación de React en el cliente

En el momento de la solicitud, en el cliente:

  1. El HTML se usa para mostrar inmediatamente una vista previa rápida no interactiva inicial de los Client y Server Components.
  2. El React Server Components Payload se usa para reconciliar los árboles de Client y Server Components renderizados y actualizar el DOM.
  3. Las instrucciones JavaScript se usan para hidratar los Client Components y hacer que la aplicación sea interactiva.

4. Almacenamiento en caché de Next.js en el cliente (Caché del enrutador)

El React Server Component Payload se almacena en la Caché del enrutador del lado del cliente - una caché en memoria separada, dividida por segmentos de ruta individuales. Esta Caché del enrutador se usa para mejorar la experiencia de navegación almacenando rutas visitadas previamente y prefetching rutas futuras.

5. Navegaciones posteriores

En navegaciones posteriores o durante la precarga (prefetching), Next.js verificará si la carga útil (payload) de los Componentes de Servidor de React está almacenada en la Caché del Enrutador (Router Cache). Si es así, omitirá enviar una nueva solicitud al servidor.

Si los segmentos de ruta no están en la caché, Next.js obtendrá la carga útil de los Componentes de Servidor de React desde el servidor y poblará la Caché del Enrutador en el cliente.

Renderizado estático y dinámico

Si una ruta se almacena en caché o no en el momento de la compilación depende de si se renderiza estática o dinámicamente. Las rutas estáticas se almacenan en caché por defecto, mientras que las rutas dinámicas se renderizan en el momento de la solicitud y no se almacenan en caché.

Este diagrama muestra la diferencia entre rutas renderizadas estática y dinámicamente, con datos almacenados en caché y no almacenados:

Cómo el renderizado estático y dinámico afecta a la Caché de Ruta Completa (Full Route Cache). Las rutas estáticas se almacenan en caché en el momento de la compilación o después de la revalidación de datos, mientras que las rutas dinámicas nunca se almacenan en caché

Aprende más sobre renderizado estático y dinámico.

Duración

Por defecto, la Caché de Ruta Completa es persistente. Esto significa que el resultado del renderizado se almacena en caché entre solicitudes de usuarios.

Invalidación

Hay dos formas de invalidar la Caché de Ruta Completa:

  • Revalidando datos: Revalidar la Caché de Datos invalidará a su vez la Caché del Enrutador al volver a renderizar los componentes en el servidor y almacenar en caché el nuevo resultado del renderizado.
  • Nuevo despliegue: A diferencia de la Caché de Datos, que persiste entre despliegues, la Caché de Ruta Completa se borra en nuevos despliegues.

Opción de exclusión

Puedes optar por no usar la Caché de Ruta Completa, o en otras palabras, renderizar componentes dinámicamente para cada solicitud entrante, mediante:

  • Usar una Función Dinámica: Esto excluirá la ruta de la Caché de Ruta Completa y la renderizará dinámicamente en el momento de la solicitud. La Caché de Datos aún puede usarse.
  • Usar las opciones de configuración de segmento de ruta dynamic = 'force-dynamic' o revalidate = 0: Esto omitirá la Caché de Ruta Completa y la Caché de Datos. Significa que los componentes se renderizarán y los datos se obtendrán en cada solicitud entrante al servidor. La Caché del Enrutador seguirá aplicándose ya que es una caché del lado del cliente.
  • Excluirse de la Caché de Datos: Si una ruta tiene una solicitud fetch que no se almacena en caché, esto excluirá la ruta de la Caché de Ruta Completa. Los datos para la solicitud fetch específica se obtendrán para cada solicitud entrante. Otras solicitudes fetch que no opten por excluirse del almacenamiento en caché seguirán almacenándose en la Caché de Datos. Esto permite una combinación de datos almacenados en caché y no almacenados.

Caché del Enrutador (Router Cache)

Términos relacionados:

Puedes ver que la Caché del Enrutador se menciona como Caché del lado del cliente (Client-side Cache) o Caché de precarga (Prefetch Cache). Mientras que Caché de precarga se refiere a los segmentos de ruta precargados, Caché del lado del cliente se refiere a toda la Caché del Enrutador, que incluye tanto segmentos visitados como precargados. Esta caché se aplica específicamente a Next.js y Componentes de Servidor, y es diferente al bfcache del navegador, aunque tiene un resultado similar.

Next.js tiene una caché en memoria del lado del cliente que almacena la carga útil (payload) de los Componentes de Servidor de React, dividida por segmentos de ruta individuales, durante la duración de una sesión de usuario. Esto se llama Caché del Enrutador.

Cómo funciona la Caché del Enrutador

Cómo funciona la Caché del Enrutador para rutas estáticas y dinámicas, mostrando MISS y HIT para navegaciones iniciales y posteriores.

A medida que los usuarios navegan entre rutas, Next.js almacena en caché los segmentos de ruta visitados y precarga las rutas a las que es probable que el usuario navegue (basándose en componentes <Link> en su viewport).

Esto resulta en una mejor experiencia de navegación para el usuario:

  • Navegación instantánea hacia atrás/adelante porque las rutas visitadas están almacenadas en caché y navegación rápida a nuevas rutas debido a la precarga y renderizado parcial.
  • No hay recarga completa de página entre navegaciones y se preserva el estado de React y del navegador.

Diferencia entre la Caché del Enrutador y la Caché de Ruta Completa:

La Caché del Enrutador almacena temporalmente la carga útil de los Componentes de Servidor de React en el navegador durante la duración de una sesión de usuario, mientras que la Caché de Ruta Completa almacena persistentemente la carga útil de los Componentes de Servidor de React y el HTML en el servidor entre múltiples solicitudes de usuarios.

Mientras que la Caché de Ruta Completa solo almacena rutas renderizadas estáticamente, la Caché del Enrutador se aplica tanto a rutas renderizadas estática como dinámicamente.

Duración

La caché se almacena en la memoria temporal del navegador. Dos factores determinan cuánto tiempo dura la caché del enrutador:

  • Sesión: La caché persiste entre navegaciones. Sin embargo, se borra al actualizar la página.
  • Período de invalidación automática: La caché de un segmento individual se invalida automáticamente después de un tiempo específico. La duración depende de si la ruta se renderiza estáticamente o dinámicamente:
    • Renderizado dinámico: 30 segundos
    • Renderizado estático: 5 minutos

Mientras que una actualización de página borrará todos los segmentos almacenados en caché, el período de invalidación automática solo afecta al segmento individual desde el momento en que se accedió o creó por última vez.

Al agregar prefetch={true} o llamar a router.prefetch para una ruta renderizada dinámicamente, puedes optar por almacenar en caché durante 5 minutos.

Invalidación

Hay dos formas de invalidar la Caché del Enrutador:

  • En una Acción de Servidor (Server Action):
    • Revalidar datos bajo demanda por ruta con (revalidatePath) o por etiqueta de caché con (revalidateTag)
    • Usar cookies.set o cookies.delete invalida la Caché del Enrutador para evitar que las rutas que usan cookies se vuelvan obsoletas (por ejemplo, autenticación).
  • Llamar a router.refresh invalidará la Caché del Enrutador y hará una nueva solicitud al servidor para la ruta actual.

Opción de exclusión

No es posible excluirse de la Caché del Enrutador.

Puedes excluirte de la precarga estableciendo la propiedad prefetch del componente <Link> en false. Sin embargo, esto seguirá almacenando temporalmente los segmentos de ruta durante 30 segundos para permitir una navegación instantánea entre segmentos anidados, como barras de pestañas, o navegación hacia atrás y adelante. Las rutas visitadas seguirán almacenadas en caché.

Interacciones de la caché

Al configurar los diferentes mecanismos de almacenamiento en caché, es importante entender cómo interactúan entre sí:

Caché de Datos y Caché de Ruta Completa

  • Revalidar o excluirse de la Caché de Datos invalidará la Caché de Ruta Completa, ya que el resultado del renderizado depende de los datos.
  • Invalidar o excluirse de la Caché de Ruta Completa no afecta a la Caché de Datos. Puedes renderizar dinámicamente una ruta que tenga tanto datos almacenados en caché como no almacenados. Esto es útil cuando la mayor parte de tu página usa datos almacenados en caché, pero tienes algunos componentes que dependen de datos que deben obtenerse en el momento de la solicitud. Puedes renderizar dinámicamente sin preocuparte por el impacto en el rendimiento de volver a obtener todos los datos.

Caché de Datos y Caché del Enrutador del lado del cliente

  • Revalidar la Caché de Datos en un Manejador de Ruta (Route Handler) no invalidará inmediatamente la Caché del Enrutador, ya que el Manejador de Ruta no está vinculado a una ruta específica. Esto significa que la Caché del Enrutador seguirá sirviendo la carga útil anterior hasta que se realice una actualización forzada o haya transcurrido el período de invalidación automática.
  • Para invalidar inmediatamente la Caché de Datos y la Caché del Enrutador, puedes usar revalidatePath o revalidateTag en una Acción de Servidor (Server Action).

APIs

La siguiente tabla proporciona un resumen de cómo diferentes APIs de Next.js afectan al almacenamiento en caché:

APICaché del EnrutadorCaché de Ruta CompletaCaché de DatosCaché de React
<Link prefetch>Almacenar
router.prefetchAlmacenar
router.refreshRevalidar
fetchAlmacenarAlmacenar
fetch options.cacheAlmacenar o Excluir
fetch options.next.revalidateRevalidarRevalidar
fetch options.next.tagsAlmacenarAlmacenar
revalidateTagRevalidar (Acción Servidor)RevalidarRevalidar
revalidatePathRevalidar (Acción Servidor)RevalidarRevalidar
const revalidateRevalidar o ExcluirRevalidar o Excluir
const dynamicAlmacenar o ExcluirAlmacenar o Excluir
cookiesRevalidar (Acción Servidor)Excluir
headers, useSearchParams, searchParamsExcluir
generateStaticParamsAlmacenar
React.cacheAlmacenar
unstable_cache (Próximamente)

Por defecto, el componente <Link> precarga automáticamente rutas desde la Caché de Ruta Completa y agrega la carga útil de los Componentes de Servidor de React a la Caché del Enrutador.

Para desactivar la precarga, puedes establecer la propiedad prefetch en false. Pero esto no omitirá la caché permanentemente, el segmento de ruta seguirá almacenándose en caché en el lado del cliente cuando el usuario visite la ruta.

Aprende más sobre el componente <Link>.

router.prefetch

La opción prefetch del hook useRouter se puede usar para precargar manualmente una ruta. Esto agrega la carga útil de los Componentes de Servidor de React a la Caché del Enrutador.

Consulta la referencia de la API del hook useRouter.

router.refresh

La opción refresh del hook useRouter se puede usar para actualizar manualmente una ruta. Esto borra completamente la Caché del Enrutador y hace una nueva solicitud al servidor para la ruta actual. refresh no afecta a la Caché de Datos ni a la Caché de Ruta Completa.

El resultado renderizado se reconciliará en el cliente mientras se preserva el estado de React y del navegador.

Consulta la referencia de la API del hook useRouter.

fetch

Los datos devueltos por fetch se almacenan automáticamente en la Caché de Datos.

// Almacenado en caché por defecto. `force-cache` es la opción predeterminada y se puede omitir.
fetch(`https://...`, { cache: 'force-cache' })

Consulta la Referencia de la API fetch para más opciones.

fetch options.cache

Puedes excluir solicitudes fetch individuales del almacenamiento en caché estableciendo la opción cache en no-store:

// Excluir del almacenamiento en caché
fetch(`https://...`, { cache: 'no-store' })

Dado que el resultado del renderizado depende de los datos, usar cache: 'no-store' también omitirá la Caché de Ruta Completa para la ruta donde se usa la solicitud fetch. Es decir, la ruta se renderizará dinámicamente en cada solicitud, pero aún puedes tener otras solicitudes de datos almacenadas en caché en la misma ruta.

Consulta la Referencia de la API fetch para más opciones.

fetch options.next.revalidate

Puedes usar la opción next.revalidate de fetch para establecer el período de revalidación (en segundos) de una solicitud fetch individual. Esto revalidará la Caché de Datos, que a su vez revalidará la Caché de Ruta Completa. Se obtendrán datos frescos y los componentes se volverán a renderizar en el servidor.

// Revalidar como máximo después de 1 hora
fetch(`https://...`, { next: { revalidate: 3600 } })

Consulta la referencia de la API fetch para más opciones.

fetch options.next.tags y revalidateTag

Next.js tiene un sistema de etiquetado de caché para un almacenamiento y revalidación de datos granular.

  1. Al usar fetch o unstable_cache, tienes la opción de etiquetar entradas de caché con una o más etiquetas.
  2. Luego, puedes llamar a revalidateTag para purgar las entradas de caché asociadas con esa etiqueta.

Por ejemplo, puedes establecer una etiqueta al obtener datos:

// Almacenar datos con una etiqueta
fetch(`https://...`, { next: { tags: ['a', 'b', 'c'] } })

Luego, llama a revalidateTag con una etiqueta para purgar la entrada de caché:

// Revalidar entradas con una etiqueta específica
revalidateTag('a')

Hay dos lugares donde puedes usar revalidateTag, dependiendo de lo que quieras lograr:

  1. Manejadores de Ruta (Route Handlers) - para revalidar datos en respuesta a un evento de terceros (por ejemplo, webhook). Esto no invalidará inmediatamente la Caché del Enrutador ya que el Manejador de Ruta no está vinculado a una ruta específica.
  2. Acciones de Servidor (Server Actions) - para revalidar datos después de una acción del usuario (por ejemplo, envío de formulario). Esto invalidará la Caché del Enrutador para la ruta asociada.

revalidatePath

revalidatePath permite revalidar manualmente los datos y volver a renderizar los segmentos de ruta debajo de una ruta específica en una sola operación. Llamar a los métodos revalidatePath revalida la Caché de Datos, lo que a su vez invalida la Caché de Ruta Completa.

revalidatePath('/')

Hay dos lugares donde puedes usar revalidatePath, dependiendo de lo que quieras lograr:

  1. Manejadores de Ruta (Route Handlers) - para revalidar datos en respuesta a un evento de terceros (ej. webhook).
  2. Acciones de Servidor (Server Actions) - para revalidar datos después de una interacción del usuario (ej. envío de formulario, clic en un botón).

Consulta la referencia de la API revalidatePath para más información.

revalidatePath vs. router.refresh:

Llamar a router.refresh limpiará la caché del enrutador y volverá a renderizar los segmentos de ruta en el servidor sin invalidar la Caché de Datos ni la Caché de Ruta Completa.

La diferencia es que revalidatePath purga la Caché de Datos y la Caché de Ruta Completa, mientras que router.refresh() no modifica la Caché de Datos ni la Caché de Ruta Completa, ya que es una API del lado del cliente.

Funciones Dinámicas

cookies, headers, useSearchParams y searchParams son funciones dinámicas que dependen de información de solicitud entrante en tiempo de ejecución. Usarlas hará que una ruta no utilice la Caché de Ruta Completa, es decir, la ruta se renderizará dinámicamente.

cookies

Usar cookies.set o cookies.delete en una Acción de Servidor invalida la Caché del Enrutador para evitar que las rutas que usan cookies queden obsoletas (ej. para reflejar cambios de autenticación).

Consulta la referencia de la API cookies.

Opciones de Configuración de Segmento

Las opciones de Configuración de Segmento de Ruta pueden usarse para sobrescribir los valores predeterminados del segmento de ruta o cuando no puedes usar la API fetch (ej. cliente de base de datos o bibliotecas de terceros).

Las siguientes opciones de Configuración de Segmento de Ruta harán que no se use la Caché de Datos ni la Caché de Ruta Completa:

  • const dynamic = 'force-dynamic'
  • const revalidate = 0

Consulta la documentación de Configuración de Segmento de Ruta para más opciones.

generateStaticParams

Para segmentos dinámicos (ej. app/blog/[slug]/page.js), las rutas proporcionadas por generateStaticParams se almacenan en la Caché de Ruta Completa en tiempo de compilación. En tiempo de solicitud, Next.js también almacenará en caché las rutas que no se conocían en tiempo de compilación la primera vez que se visitan.

Puedes deshabilitar el almacenamiento en caché en tiempo de solicitud usando la opción export const dynamicParams = false en un segmento de ruta. Cuando se usa esta opción de configuración, solo se servirán las rutas proporcionadas por generateStaticParams, y otras rutas devolverán 404 o coincidirán (en el caso de rutas comodín).

Consulta la referencia de la API generateStaticParams.

Función cache de React

La función cache de React permite memorizar el valor de retorno de una función, permitiéndote llamar a la misma función múltiples veces mientras solo se ejecuta una vez.

Como las solicitudes fetch se memorizan automáticamente, no necesitas envolverlas en cache de React. Sin embargo, puedes usar cache para memorizar manualmente solicitudes de datos en casos donde la API fetch no sea adecuada. Por ejemplo, algunos clientes de base de datos, clientes CMS o clientes GraphQL.

import { cache } from 'react'
import db from '@/lib/db'

export const getItem = cache(async (id: string) => {
  const item = await db.item.findUnique({ id })
  return item
})
import { cache } from 'react'
import db from '@/lib/db'

export const getItem = cache(async (id) => {
  const item = await db.item.findUnique({ id })
  return item
})

unstable_cache

unstable_cache es una API experimental para agregar valores a la Caché de Datos cuando la API fetch no es adecuada. Por ejemplo, al usar clientes de base de datos, clientes CMS o GraphQL.

import { unstable_cache } from 'next/cache'

export default async function Page() {
  const cachedData = await unstable_cache(
    async () => {
      const data = await db.query('...')
      return data
    },
    ['cache-key'],
    {
      tags: ['a', 'b', 'c'],
      revalidate: 10,
    }
  )()
}

Advertencia: Esta API está en desarrollo y no recomendamos usarla en producción. Se incluye aquí para mostrar la dirección futura de la Caché de Datos.