Tema
Qué es Next.js: SSR, SSG, ISR y CSR
Antes de crear tu primer proyecto, necesitas entender el concepto más importante de Next.js: dónde y cuándo se genera el HTML de cada página. Esa decisión afecta la velocidad, el SEO y el costo de tu app. Aquí aprenderás las cuatro estrategias de renderizado y cuándo usar cada una.
Concepto
El problema de una SPA
Con React + Vite (curso de React), el servidor envía un HTML casi vacío:
html
<!doctype html>
<html>
<body>
<div id="root"></div>
<script type="module" src="/assets/index-B3k9.js"></script>
</body>
</html>El navegador descarga el JavaScript, lo ejecuta, pide los datos a la API y por fin dibuja la página. Consecuencias:
- Pantalla en blanco mientras carga (peor en celulares lentos).
- SEO limitado: Google puede ejecutar JavaScript, pero redes como WhatsApp, Facebook o X sólo leen el HTML inicial al generar la vista previa de un enlace.
- Todo el trabajo recae en el dispositivo del usuario.
La solución: renderizar en el servidor
Next.js puede generar el HTML completo en el servidor, con los datos ya incluidos. El usuario ve el contenido de inmediato; luego React "hidrata" la página (le conecta los eventos) para que sea interactiva.
Analogía del restaurante:
- CSR (SPA): te dan los ingredientes y la receta, y cocinas en tu mesa.
- SSR: el chef cocina tu platillo cuando lo pides.
- SSG: los platillos ya están preparados desde la mañana; te sirven al instante.
- ISR: platillos preparados que el chef renueva cada cierto tiempo para que estén frescos.
Las cuatro estrategias
1. SSG — Static Site Generation
El HTML se genera una vez, al hacer el build (next build) y se sirve igual a todos los visitantes desde un CDN.
txt
next build ──► genera HTML ──► CDN ──► usuario (respuesta instantánea)- ✅ Lo más rápido y barato. Ideal para SEO.
- ❌ Si los datos cambian, hay que volver a hacer el build (o usar ISR).
- Usos: landing pages, páginas "Nosotros", documentación, blog con pocos cambios.
En el App Router, una página es estática por defecto si no usa datos dinámicos:
tsx
// app/nosotros/page.tsx — se genera en el build
export default function Nosotros() {
return (
<main>
<h1>Sobre nosotros</h1>
<p>Somos una agencia de desarrollo web en Guadalajara.</p>
</main>
)
}2. SSR — Server-Side Rendering
El HTML se genera en cada petición, en el servidor.
txt
usuario ──► servidor (consulta datos + genera HTML) ──► usuario- ✅ Datos siempre actualizados y personalizados (por usuario, cookies, ubicación).
- ❌ Más lento que SSG y requiere un servidor activo.
- Usos: panel de usuario, resultados de búsqueda, carrito, precios en tiempo real.
tsx
// app/dashboard/page.tsx — se genera en cada visita porque lee cookies
import { cookies } from 'next/headers'
export default async function Dashboard() {
const cookieStore = await cookies()
const tema = cookieStore.get('tema')?.value ?? 'claro'
const hora = new Date().toLocaleTimeString('es-MX')
return (
<main>
<h1>Tu panel</h1>
<p>Generado a las {hora} con el tema {tema}</p>
</main>
)
}Usar cookies(), headers(), searchParams o datos sin caché convierte la página en dinámica (SSR) automáticamente.
3. ISR — Incremental Static Regeneration
Lo mejor de ambos: la página es estática, pero se regenera en segundo plano cada cierto tiempo o cuando tú lo indicas.
txt
1ª visita: sirve HTML del build (rápido)
pasan 60 s: la siguiente visita aún recibe el HTML viejo, pero dispara la regeneración
después: todos reciben el HTML nuevo- ✅ Velocidad de SSG con datos razonablemente frescos.
- Usos: catálogo de productos, blog, noticias, páginas con miles de elementos.
tsx
// app/productos/page.tsx — se regenera como máximo cada 60 segundos
export const revalidate = 60
export default async function Productos() {
const res = await fetch('https://dummyjson.com/products?limit=10')
const { products } = await res.json()
return (
<ul>
{products.map((p: { id: number; title: string; price: number }) => (
<li key={p.id}>
{p.title} — ${p.price}
</li>
))}
</ul>
)
}También puedes regenerar bajo demanda (por ejemplo, cuando el cliente edita un producto en su panel) con revalidatePath o revalidateTag. Lo verás en Data fetching y caché.
4. CSR — Client-Side Rendering
El componente se dibuja en el navegador, como en una SPA. En Next.js lo usas para partes interactivas dentro de una página renderizada en el servidor.
tsx
'use client' // este componente se ejecuta en el navegador
import { useState } from 'react'
export default function Contador() {
const [n, setN] = useState(0)
return <button onClick={() => setN(n + 1)}>Clics: {n}</button>
}- Usos: formularios interactivos, carritos, mapas, gráficas, cualquier cosa con estado o eventos.
Comparación
| SSG | ISR | SSR | CSR | |
|---|---|---|---|---|
| Se genera | En el build | En el build + periódicamente | En cada petición | En el navegador |
| Velocidad | ⚡⚡⚡ | ⚡⚡⚡ | ⚡⚡ | ⚡ (primera carga) |
| Datos frescos | ❌ | ⏱ casi | ✅ | ✅ |
| SEO | ✅ | ✅ | ✅ | ⚠️ |
| Personalizado por usuario | ❌ | ❌ | ✅ | ✅ |
| Necesita servidor | No | Sí (o plataforma) | Sí | No |
¿Cómo elijo?
txt
¿El contenido es igual para todos?
├─ Sí → ¿Cambia seguido?
│ ├─ Casi nunca → SSG
│ └─ A veces → ISR (revalidate o bajo demanda)
└─ No (depende del usuario, cookies, búsqueda) → SSR
└─ Partes interactivas dentro → Client Components (CSR)Lo poderoso de Next.js es que mezclas estrategias en la misma app, e incluso en la misma página: la página de un producto puede ser ISR, con un botón "Agregar al carrito" que es un Client Component.
¿Qué más trae Next.js?
| Característica | Qué resuelve |
|---|---|
| App Router | Rutas creando carpetas, layouts anidados, estados de carga y error |
| Server Components | Componentes que corren sólo en el servidor: acceso directo a la base de datos y menos JavaScript en el navegador |
| Server Actions | Funciones del servidor que llamas desde formularios, sin crear una API |
| Route Handlers | Endpoints de API (/api/...) en el mismo proyecto |
| next/image | Imágenes optimizadas, redimensionadas y en formatos modernos |
| next/font | Fuentes de Google o locales sin saltos de diseño |
| Metadata API | SEO, Open Graph, sitemap y robots |
| Turbopack | Compilador rápido para desarrollo y build |
¿Next.js o React con Vite?
| Usa Next.js si... | Usa React + Vite si... |
|---|---|
| El SEO importa (tienda, blog, landing) | Es un panel interno detrás de un login |
| Quieres frontend y backend en un proyecto | Ya tienes un backend separado |
| Necesitas rendimiento en la primera carga | Quieres la configuración más simple |
| Vas a desplegar en Vercel o un servidor Node | Sólo tienes hosting estático (aunque Next también puede exportar estático) |
Buena práctica
Empieza pensando en el servidor: deja que la mayoría de tus componentes sean Server Components (estáticos o con datos) y usa Client Components sólo donde haya interactividad. Así envías menos JavaScript y tu sitio es más rápido.
Error común
Creer que "Next.js = todo SSR = más lento". Por defecto Next intenta generar todo de forma estática; sólo usa SSR cuando la página lo necesita. Revisa la salida de next build: indica qué rutas son estáticas (○) y cuáles dinámicas (ƒ).
Ejercicios
Decide qué estrategia usarías para cada página y por qué:
- La página de inicio de un despacho de abogados.
- La página de detalle de cada uno de los 5,000 productos de una tienda.
- "Mis pedidos" de un usuario con sesión iniciada.
- Un buscador de vuelos con filtros.
- El artículo de un blog que se publica dos veces por semana.
- Un mapa interactivo de sucursales dentro de la página "Contacto".
Ver solución
- SSG: el contenido casi no cambia y es igual para todos. Rápido y excelente para SEO.
- ISR: demasiados productos para regenerar todo en cada build y los precios/stock cambian. Genera los más populares en el build con
generateStaticParams, el resto bajo demanda, y revalida al editar un producto (revalidateTag). - SSR (dinámica): depende de la sesión (cookies) y es distinta para cada usuario. No debe cachearse para todos.
- SSR: depende de los filtros en la URL (
searchParams) y de disponibilidad en tiempo real. Los filtros interactivos pueden ser Client Components. - SSG o ISR: se genera estática; al publicar un artículo, se revalida bajo demanda con
revalidatePath('/blog'). - Página SSG + Client Component para el mapa (necesita JavaScript del navegador e interacción). Puedes cargarlo con
dynamic(() => import(...), { ssr: false })si la librería usawindow.
Resumen
- SSG: HTML en el build; lo más rápido. ISR: estático que se regenera. SSR: HTML en cada petición. CSR: en el navegador.
- Next.js elige estático por defecto y pasa a dinámico si usas cookies, headers,
searchParamso datos sin caché. - Puedes combinar estrategias en la misma app y en la misma página.
- Next.js agrega rutas por archivos, Server Components, Server Actions, optimización y SEO a React.