Los 4 Niveles de Cache en Next.js: El Modelo Mental que Finalmente Tiene Sentido

Programación· 6 min de lectura

Los 4 Niveles de Cache en Next.js: El Modelo Mental que Finalmente Tiene Sentido

Llevaba tres meses construyendo una aplicación en Next.js cuando me di cuenta de algo: estaba optimizando el cache completamente mal.

Tenía datos que debían refrescarse cada hora. Otros que debían servirse al instante. Algunos que solo ciertos usuarios debían ver. Y no tenía ni idea de cuál de las cuatro capas de cache debería usar en cada caso.

La documentación oficial de Next.js es buena, pero está escrita como referencia técnica. Lo que necesitaba era un modelo mental simple que conectara todo.

Hoy te comparto exactamente cómo funciona.

¿Por Qué Importa el Cache?

Antes de entrar en los detalles técnicos: el cache es la diferencia entre una aplicación que tarda 2 segundos en cargar y una que tarda 200 milisegundos.

Es la diferencia entre pagar $50/mes en infraestructura y $500/mes.

Es la diferencia entre un usuario satisfecho y uno que cierra tu sitio.

Pero aquí está el problema: Next.js no tiene *un* sistema de cache. Tiene *cuatro*, y cada uno hace cosas diferentes en momentos diferentes.

Los 4 Niveles Explicados (De Arriba a Abajo)

1. Request Memoization (En Memoria, Durante la Solicitud)

Este es el más simple pero el más incomprendido.

¿Qué hace? Si llamas a la misma función dos veces en la misma solicitud HTTP, Next.js solo la ejecuta una vez.

¿Dónde funciona? Solo en el servidor, durante el render de una página.

¿Cuánto dura? Mientras se procesa esa solicitud. Cuando termina, se olvida.

Ejemplo real:

```javascript // app/page.js async function getUserData(id) { console.log('Fetching user data...'); const res = await fetch(`https://api.example.com/users/${id}`); return res.json(); }

export default async function Page() { // Esto llama a getUserData dos veces const user = await getUserData(1); const userAgain = await getUserData(1);

// Pero solo hace una solicitud a la API // "Fetching user data..." aparece UNA sola vez en los logs

return <div>{user.name}</div>; } ```

Next.js usa `fetch()` con memoization automática. Si usas otra librería como `axios`, no obtienes este beneficio.

Caso de uso: Cuando tienes múltiples componentes que necesitan los mismos datos en la misma página.

---

2. Data Cache (En el Servidor, Entre Solicitudes)

Este es donde la mayoría de la magia sucede.

¿Qué hace? Almacena los resultados de `fetch()` entre solicitudes HTTP. Si alguien visita tu página a las 10:00 y otra persona a las 10:05, la segunda obtiene el mismo resultado cacheado.

¿Dónde funciona? En el servidor Vercel (o tu servidor, si lo despliegas en otro lugar).

¿Cuánto dura? Indefinidamente, hasta que lo invalides manualmente.

Ejemplo:

```javascript // app/posts/page.js async function getPosts() { const res = await fetch('https://api.example.com/posts', { next: { revalidate: 3600 } // Revalidar cada hora }); return res.json(); }

export default async function PostsPage() { const posts = await getPosts(); return ( <div> {posts.map(post => ( <article key={post.id}>{post.title}</article> ))} </div> ); } ```

La primera persona que carga esta página hace una solicitud real a tu API. Las siguientes 3600 personas (durante la próxima hora) obtienen el resultado cacheado sin tocar tu API.

Caso de uso: Datos que cambian lentamente (posts de blog, información de productos, configuración).

---

3. Full Route Cache (HTML Estático Pre-renderizado)

Este es el que realmente acelera todo.

¿Qué hace? Next.js pre-renderiza tu página completa a HTML estático en tiempo de build y la sirve tal cual.

¿Dónde funciona? En el CDN global (si usas Vercel) o en tu servidor estático.

¿Cuánto dura? Hasta que redeploys tu aplicación o invalidas la ruta manualmente.

Ejemplo:

```javascript // app/about/page.js export default function AboutPage() { return ( <div> <h1>Sobre Nosotros</h1> <p>Esta página se renderiza UNA sola vez en build time.</p> </div> ); } ```

Cuando haces `npm run build`, Next.js genera un archivo HTML estático para esta página. Cuando alguien la solicita, sirve el HTML precompilado directamente desde el CDN. Ningún servidor Node.js involucrado.

Tiempo de respuesta: <50ms desde cualquier parte del mundo (si usas Vercel).

Caso de uso: Páginas estáticas (About, Pricing, Landing pages). Cualquier cosa que no cambia frecuentemente.

---

4. Router Cache (En el Navegador)

Este es el más nuevo y el que menos gente entiende.

¿Qué hace? Cuando navegas entre páginas en tu aplicación Next.js, el navegador cachea los segmentos de ruta que ya visitaste.

¿Dónde funciona? En la memoria del navegador del usuario.

¿Cuánto dura? Mientras el usuario está en tu aplicación. Se limpia cuando cierra la pestaña.

Ejemplo:

```javascript // app/layout.js 'use client';

import Link from 'next/link';

export default function Layout({ children }) { return ( <> <nav> <Link href="/">Home</Link> <Link href="/products">Products</Link> <Link href="/about">About</Link> </nav> {children} </> ); } ```

Cuando haces clic en "Products", Next.js carga esa página. Cuando haces clic en "About", carga esa página. Si vuelves a hacer clic en "Products", no hace otra solicitud al servidor. Usa lo que cacheó en el navegador.

Caso de uso: Navegación rápida dentro de tu aplicación. La experiencia se siente como una app nativa.

---

El Modelo Mental Unificado

Aquí está la clave para entender todo esto:

``` ┌─────────────────────────────────────┐ │ Usuario hace clic en un enlace │ └────────────┬────────────────────────┘ │ ▼ ¿Está en Router Cache? (Navegador del usuario) │ ┌──────┴──────┐ │ SÍ │ NO ▼ ▼ Sirve del ¿Está en Full Route Cache? navegador (CDN/Servidor estático) │ ┌────┴────┐ │ SÍ │ NO ▼ ▼ Sirve del ¿Está en Data Cache? CDN (Servidor) │ ┌────┴────┐ │ SÍ │ NO ▼ ▼ Sirve del Hace fetch real servidor a tu API/DB ```

Ejemplo Práctico: Un Blog Real

Tengo un blog donde publico artículos. Algunos cambios:

  • **Artículos publicados:** Cambian cada semana. Uso `revalidate: 86400` (24 horas) en Data Cache.
  • **Página de inicio:** Muestra los últimos 5 artículos. Full Route Cache con ISR (Incremental Static Regeneration).
  • **Página de contacto:** Nunca cambia. Full Route Cache, sin revalidación.
  • **Dashboard del usuario:** Datos personales que cambian constantemente. Sin cache, o cache muy corto.

```javascript // app/blog/[slug]/page.js export async function generateStaticParams() { // Pre-renderiza todos los artículos en build time const posts = await fetch('https://api.example.com/posts').then(r => r.json()); return posts.map(post => ({ slug: post.slug })); }

async function getPost(slug) { const res = await fetch(`https://api.example.com/posts/${slug}`, { next: { revalidate: 86400 } // Revalidar cada 24 horas }); return res.json(); }

export default async function PostPage({ params }) { const post = await getPost(params.slug); return <article>{post.content}</article>; } ```

La Conclusión Práctica

No necesitas entender los detalles internos de Next.js. Solo necesitas saber:

1. Request Memoization: Usa automáticamente si llamas a `fetch()` dos veces. 2. Data Cache: Configura con `next: { revalidate: segundos }` en tus `fetch()`. 3. Full Route Cache: Sucede automáticamente en páginas estáticas. Usa ISR para revalidación. 4. Router Cache: Sucede automáticamente en el navegador cuando usas `<Link>`.

La mayoría de problemas de rendimiento que veo vienen de no usar estos niveles correctamente. Gente haciendo `fetch()` sin `revalidate`, o usando páginas dinámicas cuando podrían ser estáticas.

Próxima vez que optimices una página, pregúntate: ¿En qué capa debería estar este dato?

La respuesta correcta te ahorrará miles en infraestructura.