Tu App en Next.js Descarga JavaScript Que No Necesita
Tienes una dashboard que carga 847KB de JavaScript.
El 60% de ese JavaScript renderiza tablas de datos, cards de productos y listas de categorías.
Ninguno de esos componentes necesita onClick. Ni useState. Ni acceso a window.
El problema real no es cuánto JavaScript envías. Es que envías JavaScript para renderizar cosas que podrían renderizarse en el servidor.
Los Server Components existen desde React 18 y Next.js 13, pero el 90% de developers los usa para páginas estáticas cuando su verdadero poder está en las aplicaciones dinámicas con datos complejos.
Por Qué Tus Client-Side Waterfalls Son Peores de Lo Que Crees
Cada vez que usas useEffect para hacer fetch de datos en el cliente, creas una cadena de dependencias secuenciales.
Tres requests secuenciales. Tres bloques de carga visible. Tres oportunidades para que el usuario vea un skeleton en lugar de contenido.
La mayoría developers resuelven esto con loading states de Suspense, pero eso no elimina el waterfall. Solo lo disfraza con animaciones de carga.
❌ Lo que la mayoría hace:
- Fetch en
useEffectcon dependencias encadenadas - Loading states para cada nivel de profundidad
- Skeleton components que muestran estructura vacía
✅ Lo que Server Components permiten:
- Fetch paralelo en el servidor sin dependencias
- Componente como unidad de datos y renderizado
- Cero JavaScript adicional en el bundle
Server Components No Son Para Contenido Estático
Aquí está el misconception más común: "Server Components son para páginas sin interactividad".
Falso.
Server Components son para cualquier componente que no necesite acceso al browser APIs ni eventos de usuario.
Una dashboard de analytics tiene charts interactivos (Client Components) pero también tiene tablas de métricas, headers con datos agregados, y filtros de fecha que simplemente renderizan valores (Server Components).
La diferencia clave:
El segundo approach elimina completamente la fase de hydration. No hay JavaScript interpretándose en el cliente para reconstruir el árbol de componentes.
Cómo Identificar Qué Componente Debe Ser Server
Criterio 1: ¿Necesita interactividad?
Si el componente responde a clicks, scrolls, drags, o cualquier evento de usuario → Client Component.
Si solo muestra datos que cambian cuando la página se recarga → Server Component.
Criterio 2: ¿Accede a browser APIs?
window, document, localStorage, navigator, IntersectionObserver → Client Component.
Base de datos, filesystem, API externa, variables de entorno → Server Component.
Criterio 3: ¿Cuántos datos recibe?
Un componente que recibe 50 props para renderizar una tabla de 200 filas → probablemente debería ser Server Component con la query en el mismo archivo.
Aquí tienes un ejemplo real de refactor:
El Server Component ejecuta findMany() directamente. No hay API entre medias. No hay estado de loading. No hay JavaScript en el bundle.
Composición de Server y Client Components
El App Router de Next.js permite anidar Server y Client Components, pero hay una regla crítica: un Client Component puede importar Server Components, pero un Server Component no puede importar Client Components directamente.
La solución: pass Server Components como children a Client Components.
La composición correcta coloca la lógica de interactividad en Client Components (la envoltura) mientras el contenido interno se mantiene en Server Components.
Parallel Fetching: La Ventaja Real
El mayor benefit de Server Components no es eliminar JavaScript. Es el parallel fetching.
En un árbol de componentes tradicional con fetch en cliente:
- Parent componente se monta
- Parent hace fetch de sus datos
- Parent renderiza children
- Child1 se monta, hace fetch de sus datos
- Child2 se monta, hace fetch de sus datos
- Child3 se monta, hace fetch de sus datos
Los steps 4, 5, 6 son secuenciales porque React necesita renderizar cada child antes de que se monte.
Con Server Components:
Tres queries, una sola request al servidor, respuesta compilada en un serialized component tree que React reconstruye sin hydration overhead.
El tiempo total es el del request más lento, no la suma de todos.
Midiendo el Impacto Real en Bundle Size
Next.js Bundle Analyzer te muestra exactamente cuánto JavaScript elimina cada Server Component.
Ejecuta:
Verás visualmente qué componentes pesan en el cliente y cuáles son "zero-bundle".
Para una dashboard típica con 15 componentes de datos:
- Sin Server Components: 847KB de JavaScript
- Con Server Components apropiados: 312KB de JavaScript
- Reducción: ~63%
Los 535KB eliminados no son código muerto. Son componentes que ahora se ejecutan en servidor y no necesitan hydration.
Framework: Implementación Paso a Paso
Step 1: Auditoría de Componentes
Abre tu proyecto en /app y lista cada componente.
Marca con color rojo los que usan:
useState,useEffect,useReducer- Event handlers (
onClick,onChange, etc.) - Browser APIs
Marca con color verde los que solo:
- Renderizan datos recibidos como props
- Ejecutan lógica de display sin efectos secundarios
-usan otros Server Components
Step 2: Extrae la Lógica de Datos
Para cada componente verde, mueve el fetch del cliente al servidor.
Step 3: Identifica la Frontera Client/Server
Ubica el punto donde la interactividad empieza.
El Client Component solo debe existir donde sea estrictamente necesario.
Step 4: Implementa Suspense Boundaries
Para datos lentos, envuelve en Suspense sin convertir a Client Component:
El Skeleton es un Client Component mínimo. El contenido pesado es un Server Component.
Step 5: Verifica con Bundle Analyzer
Ejecuta el análisis después de cada refactor. Si el bundle no decrece, es quemoviste lógica al servidor pero dejaste componentes clientes innecesarios.
La Pregunta Que Dejas de Hacerte
¿Realmente necesito este useEffect o puedo mover esta query a un Server Component?
La respuesta, en la mayoría de casos, es que sí puedes.
La mayoría de aplicaciones Next.js que hojean tutoriales de 2023 tienen arquitecturas de 2020: todo en cliente, fetch en useEffect, estados de loading por todas partes.
Server Components no son una feature avanzada para edge cases. Son el default behavior que Next.js 16 optimiza agresivamente.
Cada vez que escribes 'use client' sin una razón específica, estás eligiendo pagar el precio de hydration y bundle size por defecto.
La próxima vez que inicies un componente, pregúntate: ¿realmente necesito que esto se ejecute en el navegador?
Si la respuesta es no, ya tienes tu Server Component.
Artículos relacionados
- Patrones de Diseño para Apify Actors: Cómo Construir Extracción de Datos que No Falla en Producción
- Coordinación Multi-Agente: Por Qué los Frameworks de 19K Stars Son Sobreingeniería
- RLS Security Patterns en Supabase: El Approach que el 90% de Developers Implementa Mal
---
¿Quieres recibir contenido como este cada semana? Suscríbete a mi newsletter

