Server Components en Next.js explicados sin humo

En los últimos meses los Server Components han ganado mucha atención en la comunidad de React y Next.js. A diferencia de los componentes tradicionales, que se renderizan en el cliente, los Server Components se ejecutan exclusivamente en el servidor y devuelven HTML listo para enviarse al navegador. En este artículo vamos a desmitificar su funcionamiento, ver sus ventajas y limitaciones, y acabar con un ejemplo práctico que puedas copiar en tu proyecto.
¿Qué son los Server Components?
Un Server Component es simplemente una función de React que se ejecuta en el entorno Node.js de Next.js. No tiene acceso al window, a los eventos del navegador ni a APIs del cliente. Su única misión es generar markup basado en datos que normalmente se obtienen del backend. Al no cargar código JavaScript al cliente, reducimos el bundle y mejoramos el Time to First Byte (TTFB).
Cómo se diferencian de los componentes tradicionales
- Renderizado: Los Server Components se renderizan en el servidor, mientras que los componentes habituales (Client Components) lo hacen en el cliente.
- Tamaño del bundle: Sólo los Client Components aparecen en el bundle JavaScript que se envía al navegador.
- Acceso a datos: Los Server Components pueden usar
fetch, bases de datos o cualquier API del servidor sin necesidad de crear rutas API separadas. - Interactividad: No pueden contener estado local, hooks como
useStateo efectos, pues no existen en el entorno del servidor.
Cuándo usar Server Components
Utilízalos siempre que necesites:
- Obtener datos que no cambian frecuentemente y que no requieren interacción del usuario.
- Renderizar partes estáticas de una página, como cabeceras, listados de productos o información de usuario.
- Reducir la carga de JavaScript en el cliente y mejorar la velocidad percibida.
En cambio, si tu componente necesita manejar eventos, estado local o acceder al DOM, sigue siendo un Client Component.
Configuración básica en Next.js 13+
Para usar Server Components basta con crear archivos dentro de la carpeta app. Por defecto, todos los componentes son Server Components, salvo que añadas la directiva 'use client' al inicio del archivo.
export default async function Greeting(){ const data = await fetch('/api/user'); const user = await data.json(); return <div>Hola, {user.name}</div> }En el ejemplo anterior, Greeting se ejecuta en el servidor, llama a una API interna y devuelve un div con el nombre del usuario. No se envía ningún JavaScript adicional al cliente.
Mezclando Server y Client Components
Next.js permite combinar ambos tipos sin problemas. Un Server Component puede importar y renderizar un Client Component, pero al revés no es posible. Imagina una lista de productos que se genera en el servidor y, dentro de cada fila, un botón Agregar al carrito que sí necesita interacción.
// server component
export default async function ProductList(){ const res = await fetch('https://api.example.com/products'); const products = await res.json(); return <ul>{products.map(p=><li key={p.id}><ProductItem product={p} /></li>)}</ul> }// client component (ProductItem.jsx)
'use client';
import { useState } from 'react';
export default function ProductItem({product}){ const [count, setCount] = useState(0); return <div> <h4>{product.name}</h4> <button onClick={()=>setCount(c=>c+1)}>Añadir ({count})</button> </div> }El componente ProductList se renderiza en el servidor, mientras que ProductItem lleva la directiva 'use client' y se envía al navegador para manejar la interacción.
Limitaciones y buenas prácticas
Aunque los Server Components son poderosos, tienen algunas restricciones que conviene conocer:
- No pueden usar hooks de React que dependan del ciclo de vida del cliente (
useEffect,useLayoutEffect, etc.). - No pueden acceder a APIs del navegador (
localStorage,document, etc.). - El tamaño del HTML generado puede crecer si se incluyen demasiados datos; siempre filtra la información que realmente necesitas.
Una buena práctica es mantener la lógica de negocio y la obtención de datos en los Server Components y delegar únicamente la interactividad a componentes cliente ligeros.
Conclusión
Los Server Components de Next.js nos ofrecen una forma elegante de combinar lo mejor del renderizado del lado del servidor con la flexibilidad de React. Al utilizarlos de forma estratégica, podemos reducir el peso del bundle, mejorar el TTFB y ofrecer una experiencia más fluida al usuario. Prueba a migrar partes estáticas de tu aplicación a Server Components y mide el impacto: notarás la diferencia sin necesidad de “humo” ni complicaciones.