Post relacionados

Fundamentos Next.js
Fundamentos Next.js: Components, navegación Link, estilos y tipos de letra.
(1)


Curso de Next.js gratuito
Curso de Next.js gratis desde Cero: Domina el Framework de React para aplicaciones web
(1)

next.config.js y variables de entorno en Next.js
Domina next.config.js y variables de entorno en Next.js 15: Configuración esencial
(1)

En esta clase del Curso de Next.js desde cero, descubrirás cómo combinar el poder de la Generación Estática Incremental (ISR) con las nuevas Server Actions en Next.js 15, una página web que implementa ISR mejora su tiempo de carga significativamente.
En esta clase te enseñaré a crear páginas estáticas rápidas que se actualizan periódicamente, mientras manejas mutaciones de datos directamente desde el cliente gracias a las Server Actions. Aprenderás a configurar tiempos de revalidación, manejar actualizaciones en tiempo real y optimizar el rendimiento de tu aplicación.
Perfecto para desarrolladores que buscan llevar sus habilidades con Next.js 15 al siguiente nivel, combinando lo mejor del rendimiento estático con la interactividad dinámica.
Tabla de contenido
- 1 ¿Qué es SSR (Server-Side Rendering) en Next.js?
- 2 🔹 ¿Cómo funciona SSR en Next.js?
- 3 Configuración para SSR (Server-Side Rendering)
- 4 Generación Estática Incremental (ISR) en Next.js 15
- 5 Configuración Básica de ISR en Next.js 15
- 6 Endpoint de prueba para generar nuestras páginas estáticas
- 7 Server Actions y Mutaciones de Datos en Next.js
¿Qué es SSR (Server-Side Rendering) en Next.js?
SSR (Renderizado en el Lado del Servidor) es una técnica en Next.js donde las páginas se generan en el servidor en cada solicitud (request), en lugar de hacerse en el cliente (navegador). Esto mejora el SEO, el rendimiento inicial y la experiencia de usuario, especialmente para contenido dinámico.
🔹 ¿Cómo funciona SSR en Next.js?
- El navegador solicita una página (ej: /productos/123).
- Next.js procesa la página en el servidor (fetch de datos, renderizado de React).
- Envía el HTML completo al cliente (listo para mostrar).
- El cliente hidrata (hydrate) la página para hacerla interactiva.
Configuración para SSR (Server-Side Rendering)
Comencemos primero recordando como entregaríamos una página que se renderiza del lado del servidor, para ello agregamos una nueva ruta dinámica donde visualizaremos los post qeu confirman nuestro blog que creamos la clase pasada.
// app/blog/[slug]/page.tsx
import { notFound } from "next/navigation";
interface Post{
id: string;
title: string;
slug: string;
createdAt: string;
}
async function getPost(slug: string): Promise<Post | undefined> {
try {
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_URL}/api/posts/${slug}`,
{
next: { tags: ["posts"], revalidate: 3600 },
}
);
if (response.status !== 200) {
return undefined;
}
return (await response.json())?.data as Post;
} catch (error) {
console.log("Error getPost -- " + error);
return undefined;
}
}
export default async function PostPage({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const page = await params;
const post = await getPost(page.slug);
if (!post) {
notFound();
}
return (
<article>
<h1>{post?.title}</h1>
<p>{post?.createdAt}</p>
<p>{`Actualización: ${Date.now()}`}</p>
</article>
);
}
Generación Estática Incremental (ISR) en Next.js 15
La Generación Estática Incremental (ISR) en Next.js 15 revoluciona la forma en que construimos aplicaciones web, combinando los beneficios de la generación estática con la capacidad de actualizar contenido sin necesidad de reconstruir todo el sitio, esta característica es ideal para sitios con contenido dinámico que requiere actualizaciones frecuentes.
¿Qué es ISR y por qué usarla en Next.js 15?
ISR (Incremental Static Regeneration) permite:
- Generar páginas estáticas en tiempo de compilación
- Actualizar contenido obsoleto bajo demanda
- Reducir la carga en el servidor
- Mejorar el rendimiento y la experiencia del usuario
Configuración Básica de ISR en Next.js 15
Ahora, ya que tenemos funcionando nuestra página como SSR, podeos hacerla estática para que la página se construya cuando el usuario la visita la primera vez, y después, lo que vea es la página cacheada y su carga sea mucho más rápida:
- Sólo debemos agregar la función generateStaticParams para establecer un arreglo de nuestras URLs
- Y a través de revalidate el tiempo en que se invalidará el cache y la página debe volverse a construir.
// app/blog/[slug]/page.tsx
/**
* Definimos las urls de nuestro sitio
*/
export async function generateStaticParams() {
const posts: Post[] = await fetch(
`${process.env.NEXT_PUBLIC_API_URL}/api/posts`,
{
next: { tags: ["posts"], revalidate: 3600 },
}
).then((res) => res.json());
return posts.map((post) => ({ slug: post.slug }));
}
export const revalidate = 3600 // Revalida cada hora
async function getPost(slug: string) {
//Obtención del post
}
export default async function PostPage({ params }: { params: { slug: string } }) {
//Contenido de tu página web
}
Este ejemplo muestra:
generateStaticParams
para generar rutas estáticasrevalidate
para establecer el intervalo de actualización- Fetch de datos dinámicos con actualización periódica
Gracias por tu calificación
(1)
Endpoint de prueba para generar nuestras páginas estáticas
// app/api/posts/[post]/route.ts
import { NextResponse } from "next/server";
export async function GET(
request: Request,
{ params }: { params: Promise<{ post: string }> }
) {
try {
const posts = [
{
id: "post-1",
title: "Post 1",
slug: "/blog/post-1",
createdAt: "2025-04-01",
},
{
id: "post-2",
title: "Post 2",
slug: "/blog/post-2",
createdAt: "2025-04-02",
},
{
id: "post-3",
title: "Post 3",
slug: "/blog/post-3",
createdAt: "2025-04-03",
},
];
const { post } = await params;
if (!post || post === "") {
return NextResponse.json({ error: "Not found" }, { status: 404 });
}
const dataPost = posts.find((p) => p.id === post);
if (dataPost) {
return NextResponse.json({ data: dataPost, error: "" });
} else {
return NextResponse.json({ error: "Not found" }, { status: 404 });
}
} catch (error) {
return NextResponse.json(
{ error: "Failed to fetch posts: " + error },
{ status: 500 }
);
}
}
ISR Avanzado con On-demand Revalidation
Next.js 15 permite revalidación bajo demanda mediante webhooks, si deseamos que nuestra página muestre nueva información antes del tiempo de revalidate, podemos crear un endpoint para invalidar el cache maualmente y reconstruyamos la página manualmente.
// app/api/revalidate/route.ts
import { revalidatePath } from "next/cache";
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const secret = searchParams.get("secret");
const path = searchParams.get("path");
if (secret !== process.env.REVALIDATE_SECRET) {
return Response.json("Invalid secret", { status: 401 });
}
try {
if (!path) {
return Response.json("Invalid path", { status: 401 });
}
await revalidatePath(path);
return Response.json({ revalidated: true, now: Date.now() });
} catch (err) {
return Response.json(
{ message: "Error revalidating: " + err },
{ status: 500 }
);
}
}
Este endpoint puede llamarse cuando:
- Se actualiza contenido en tu CMS
- Los usuarios realizan acciones importantes
- Necesitas actualización inmediata de contenido
Mejores Prácticas para ISR en Next.js 15
- Elige tiempos de revalidación estratégicos: Balancea frecuencia y rendimiento
- Combina ISR con On-demand: Para contenido crítico que debe actualizarse inmediatamente
- Maneja estados de carga: Durante la regeneración
- Monitoriza el rendimiento: Ajusta los tiempos según las métricas
- Usa fallback: Para rutas dinámicas no generadas
Gracias por tu calificación
(1)
Server Actions y Mutaciones de Datos en Next.js
Las Server Actions en Next.js 15 revolucionan la forma en que manejamos mutaciones de datos, permitiendo ejecutar código del lado del servidor directamente desde componentes React. Esta característica elimina la necesidad de crear endpoints API manualmente para operaciones CRUD básicas.
¿Qué son las Server Actions?
Las Server Actions son funciones asíncronas que se ejecutan en el servidor pero se llaman desde el cliente. Next.js 15 las ha integrado profundamente en el App Router, ofreciendo:
- Mutaciones directas desde formularios
- Revalidación de caché
- Seguridad mejorada con protección CSRF (Cross-Site Request Forgery)
Configuración Básica
Primero, habilita Server Actions en tu next.config.js, si has creado tu proyecto como lo hicimos en este curso, no es necesario agregarlo, ya que esta activo por default en next.js 15.
// next.config.js
module.exports = {
experimental: {
serverActions: true,
}
}
Ejemplo 1: Formulario de Contacto con server actions en Next.js
Vamos a crear un formulario de contacto y la información no la enviaremos al servidor a través de un endpoint, lo haremos utilizando un server action, lo cual, que es precisamente una de las ventajas de utilizar server action, podemos ahorrarnos algunos endpoints en nuestra api.
// app/contact/page.tsx
import { revalidatePath } from 'next/cache'
export default function ContactPage() {
async function submitContactForm(formData: FormData) {
'use server'
const name = formData.get('name')
const email = formData.get('email')
const message = formData.get('message')
await db.contact.create({
data: { name, email, message }
})
revalidatePath('/contact')
redirect('/thank-you')
}
return (
<form
action={submitContactForm}
className="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4"
>
<div className="mb-4">
<label
className="block text-gray-700 text-sm font-bold mb-2"
htmlFor="name"
>
Nombre
</label>
<input
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
id="name"
type="text"
placeholder="Tu nombre"
name="name"
required
/>
</div>
<div className="mb-4">
<label
className="block text-gray-700 text-sm font-bold mb-2"
htmlFor="email"
>
Email
</label>
<input
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
id="email"
type="email"
placeholder="tu@email.com"
name="email"
required
/>
</div>
<div className="mb-6">
<label
className="block text-gray-700 text-sm font-bold mb-2"
htmlFor="message"
>
Mensaje
</label>
<textarea
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline h-32"
id="message"
placeholder="Escribe tu mensaje aquí..."
name="message"
required
></textarea>
</div>
<div className="flex items-center justify-between">
<button
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline w-full"
type="submit"
>
Enviar Mensaje
</button>
</div>
</form>
)
}
Mejores Prácticas con Server Actions
- Separa las acciones en archivos independientes
- Implementa estados para mejor UX
- Revalida datos después de mutaciones
- Protege acciones sensibles con autenticación
Gracias por tu calificación
(1)
🧐 Autoevaluación: ISR y Server Actions Next.js
¿Cómo se combinan Server Actions con ISR para actualizar contenido estático en Next.js 15?
¿Qué ventaja clave ofrece usar Server Actions en lugar de API endpoints tradicionales en Next.js 15?
Al implementar ISR en Next.js 15, ¿cuál es el propósito principal del parámetro revalidate en fetch?

Juan Carlos García
Desarrollador de software / SEO / Ing. eléctrico - electrónico UNAM
Durante años he desarrollado plataformas dedicadas al rastreo satelital y varios sitios web que se encuentran en la primera página de Google, y hoy quiero compartir contigo lo que se en tecnologías como: Node JS, PHP, C# y Bases de datos.
Si quieres apoyarme sígueme en mis redes sociales y suscríbete a mi canal de YouTube.