SSR vs SSG con Claude Code: estrategia de renderizado en Next.js y Astro
Compara SSR, SSG, ISR y export estático en Next.js/Astro con Claude Code, ejemplos ejecutables y verificación.
Primero aclara los términos
Elegir entre SSR y SSG no consiste solo en escoger la opción más rápida. SSR significa server-side rendering: el servidor genera el HTML cuando llega una petición. SSG significa static site generation: el HTML se genera durante el build y luego se sirve desde CDN o hosting estático. ISR, Incremental Static Regeneration, es el punto intermedio: se sirve una página estática, pero se vuelve a generar por tiempo o por un evento de revalidación.
La confusión habitual en Next.js App Router es pensar que Server Component significa SSR en cada petición. No es así. En la documentación actual de Dynamic Route Segments, los ejemplos TypeScript tratan params como Promise. Si necesitas indicar que el render debe esperar una petición real, la API actual es connection.
Si le dices a Claude Code “haz esta página más rápida”, puede mover demasiado contenido a estático y congelar inventario, búsqueda o UI de miembros. Si le pides SSR para todo, puedes pagar con peor TTFB y más coste de servidor. Lo práctico es pedir primero una matriz de rutas: frescura de datos, personalización, frecuencia de actualización, impacto en monetización y comando de verificación.
Comparación y casos reales
| Pregunta | SSG | ISR | SSR |
|---|---|---|---|
| Cuándo se genera HTML | Durante el build | Build y revalidación | En cada petición |
| Mejor para | Artículos, docs, landings | Productos, categorías, noticias | Paneles, búsqueda, carrito |
| Frescura | Foto del build | Por tiempo o evento | Casi actual |
| Coste | Bajo | Medio | Suele ser mayor |
| Error común | Builds largos o contenido viejo | Puede verse contenido antiguo un momento | Lento sin caché |
Caso 1: blog o documentación. Si el cuerpo, OGP, enlaces internos y CTA quedan fijos al publicar, SSG es la opción más limpia. Reconstruyes cuando cambie el contenido. Si también necesitas reducir JavaScript, revisa code splitting con Claude Code.
Caso 2: una página de producto. Precio, disponibilidad y orden de categorías pueden cambiar cada pocos minutos, pero la mayoría de visitas necesita una respuesta muy rápida. ISR encaja bien. La guía oficial de ISR en Next.js indica que ISR funciona con el runtime Node.js y no con static export.
Caso 3: panel de cuenta. Cookies, permisos, facturación, notificaciones y recomendaciones privadas dependen de la petición. Trátalo como SSR y define cabeceras de caché claras. Si tu equipo evalúa edge para rutas dinámicas, revisa edge computing con Claude Code después de decidir qué datos pueden acercarse al usuario.
Ejemplo SSR en Next.js
Este ejemplo se puede copiar en un proyecto Next.js App Router. Usa dummyjson.com, así que no necesitas API key. connection() y cache: "no-store" dejan claro durante la revisión que la página se resuelve en tiempo de petición.
// app/products/[id]/page.tsx
import { notFound } from "next/navigation";
import { connection } from "next/server";
type Product = {
id: number;
title: string;
price: number;
stock: number;
updatedAt: string;
};
async function getProduct(id: string): Promise<Product | null> {
await connection();
const res = await fetch(`https://dummyjson.com/products/${id}`, {
cache: "no-store",
});
if (res.status === 404) return null;
if (!res.ok) throw new Error(`Failed to load product: ${res.status}`);
const data = (await res.json()) as {
id: number;
title: string;
price: number;
stock: number;
meta?: { updatedAt?: string };
};
return {
id: data.id,
title: data.title,
price: data.price,
stock: data.stock,
updatedAt: data.meta?.updatedAt ?? new Date().toISOString(),
};
}
export default async function ProductPage({
params,
}: {
params: Promise<{ id: string }>;
}) {
const { id } = await params;
const product = await getProduct(id);
if (!product) notFound();
return (
<main>
<h1>{product.title}</h1>
<p>Price: ${product.price.toLocaleString("en-US")}</p>
<p>Stock: {product.stock}</p>
<p>Updated: {new Date(product.updatedAt).toLocaleString("es-ES")}</p>
</main>
);
}
El fallo más común es meter cookies() o headers() en un layout compartido porque parece cómodo. Esas APIs dependen de la petición y pueden volver dinámicas rutas que antes eran estáticas. Si ese layout envuelve artículos, puedes perder SSG sin darte cuenta. Pide a Claude Code una lista de rutas afectadas antes de aceptar el cambio.
Separar SSG, ISR y export estático
SSG e ISR pueden sentirse igual para el visitante, pero se operan de forma distinta. SSG se actualiza al reconstruir. ISR se actualiza tras una ventana de tiempo o un evento. El export estático usa output: "export" para generar una carpeta out servible sin Node.js. La guía oficial de Static Exports explica que next build puede generar un archivo HTML por ruta para hosting estático.
// app/catalog/[id]/page.tsx
import { notFound } from "next/navigation";
export const revalidate = 3600;
type Product = {
id: number;
title: string;
description: string;
};
export async function generateStaticParams() {
return ["1", "2", "3"].map((id) => ({ id }));
}
async function getProduct(id: string): Promise<Product | null> {
const res = await fetch(`https://dummyjson.com/products/${id}`, {
next: { revalidate: 3600, tags: [`product:${id}`] },
});
if (res.status === 404) return null;
if (!res.ok) throw new Error(`Failed to load product: ${res.status}`);
return (await res.json()) as Product;
}
export default async function CatalogPage({
params,
}: {
params: Promise<{ id: string }>;
}) {
const { id } = await params;
const product = await getProduct(id);
if (!product) notFound();
return (
<article>
<h1>{product.title}</h1>
<p>{product.description}</p>
</article>
);
}
// next.config.mjs
const nextConfig = {
output: "export",
images: {
unoptimized: true,
},
};
export default nextConfig;
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"export:check": "next build && npx serve out"
}
}
No mezcles export estático e ISR como si fueran lo mismo. El export estático sirve para hosting estático. Si necesitas cookies, revalidación bajo demanda, Server Functions o SSR real, necesitas un runtime de servidor. Antes de que Claude Code escriba código, especifica si vas a Cloudflare Pages estático, contenedor Node, Vercel, Netlify u otro destino.
Astro: estático y on-demand
Astro parte de generación estática por defecto. La documentación oficial de Astro on-demand rendering indica que páginas, rutas y endpoints se prerenderizan en build; con un adapter de servidor, una ruta concreta puede usar export const prerender = false para renderizarse bajo demanda.
---
// src/pages/docs/[slug].astro
export async function getStaticPaths() {
const docs = [
{ slug: "ssr", title: "SSR guide" },
{ slug: "ssg", title: "SSG guide" },
];
return docs.map((doc) => ({
params: { slug: doc.slug },
props: { doc },
}));
}
const { doc } = Astro.props;
---
<html lang="es">
<body>
<article>
<h1>{doc.title}</h1>
<p>This page was generated at build time.</p>
</article>
</body>
</html>
---
// src/pages/account.astro
export const prerender = false;
const session = Astro.cookies.get("session")?.value;
const name = session ? "Masa" : "Guest";
Astro.response.headers.set("Cache-Control", "private, no-store");
---
<html lang="es">
<body>
<h1>Account</h1>
<p>Hello, {name}.</p>
</body>
</html>
El riesgo en Astro es olvidar el adapter. Una página puede verse bien en local, pero on-demand rendering necesita runtime de servidor en producción. Pide a Claude Code revisar astro.config.mjs, la plataforma de despliegue y cada override de prerender.
Comandos de verificación y prompt
La estrategia de renderizado no se valida solo leyendo código. Mira build output, cabeceras, logs de caché y métricas como TTFB y LCP. Para ISR, la guía oficial recomienda probar comportamiento de producción con next build y next start.
# Next.js: production behavior
npm run build
npm run start
# In another terminal
curl -I http://localhost:3000/catalog/1
curl -I http://localhost:3000/products/1
# ISR cache debugging
NEXT_PRIVATE_DEBUG_CACHE=1 npm run start
# Astro
npm run build
npm run preview
El prompt debe pedir registro de decisión, no solo código:
Goal: classify every route in a Next.js/Astro site as SSR, SSG, ISR, or static export.
Inspect:
- app/ or src/pages/ routes
- cookies(), headers(), searchParams, connection(), cache: "no-store"
- generateStaticParams(), revalidate, output: "export", Astro prerender
- monetization pages, member pages, articles, product pages, and search pages
Constraints:
- Do not break SEO metadata or internal links
- Keep npm run build passing before and after
- Return a table with the chosen strategy, reason, touched files, and verification command
Errores concretos
Primero, meter contenido específico del usuario dentro de un artículo estático. Nombres de miembros, recomendaciones privadas y precios ocultos no deben quedar en HTML SSG. Mantén el artículo estático y mueve la personalización a un componente cliente o una sección claramente dinámica.
Segundo, poner intervalos ISR demasiado bajos. revalidate = 1 suele devolver el coste al servidor. Si necesitas precisión, usa revalidación bajo demanda. Si necesitas datos en tiempo real, usa SSR.
Tercero, elegir export estático y añadir después funcionalidades de servidor. Auth, UI basada en cookies, Route Handlers de servidor e ISR requieren runtime. El hosting estático es excelente, pero no reemplaza un servidor.
Cuarto, aceptar la propuesta de Claude Code solo porque parece rápida. En un sitio monetizado, el rendimiento es una parte de la calidad. También importan OGP, datos estructurados, enlaces internos, anuncios, tracking de CTA, LCP y CLS. Después de decidir, revisa optimización de rendimiento con Claude Code.
Recomendación con monetización
Para un negocio de contenido como ClaudeCodeLab, usa SSG por defecto en artículos, tutoriales, comparativas y páginas de entrada. Usa ISR en catálogos, categorías y superficies que toleran contenido brevemente antiguo. Usa SSR en áreas de miembros, búsqueda, carrito, checkout y cualquier ruta con datos privados de la petición.
Para empezar con un flujo práctico, descarga la chuleta gratuita de Claude Code. Para plantillas y paquetes de implementación, revisa la página de productos. Si tu equipo necesita estrategia de rutas, permisos, revisión de código, analítica y formación de despliegue, empieza por formación y consultoría de Claude Code.
Lo que verifiqué en la práctica
Para esta actualización revisé Dynamic Route Segments, connection, ISR, Static Exports, Astro on-demand rendering y Claude Code overview en la documentación oficial. En el flujo de contenido de Masa, la división más estable fue SSG para artículos, ISR para productos y categorías, y SSR para cuenta y búsqueda. El paso más útil con Claude Code fue pedir la matriz de rutas antes de cambiar código. Esa tabla detectó pronto el uso accidental de cookies en páginas estáticas y dejó cada decisión con razón y comando de verificación.
PDF gratis: cheatsheet de Claude Code
Introduce tu email y descarga una hoja con comandos, hábitos de revisión y flujos seguros.
Cuidamos tus datos y no enviamos spam.
Sobre el autor
Masa
Ingeniero enfocado en workflows prácticos con Claude Code.