Next.js
Performance en Next.js
Explica cómo diagnosticar rendimiento desde CDN y servidor hasta datos, RSC, hidratación y navegador mediante Core Web Vitals, traces y budgets.
- Última actualización
- Actualizada
- Nivel
- Aplicación
Next.js
Explica cómo diagnosticar rendimiento desde CDN y servidor hasta datos, RSC, hidratación y navegador mediante Core Web Vitals, traces y budgets.
El rendimiento de Next.js atraviesa CDN, servidor, caché, datos, RSC payload, JavaScript, hidratación y trabajo del navegador. Optimizar significa identificar qué recurso domina una experiencia concreta y corregir esa capa; no marcar todo como estático ni añadir memoización de React sin evidencia.
user action
→ network/CDN
→ Proxy/runtime
→ data/cache
→ server render + stream
→ RSC/HTML/JS/CSS/assets
→ parse/hydrate
→ layout/paint/interactionCada fase tiene métricas y herramientas distintas.
No preguntes “¿la app es rápida?”. Define:
Luego mide dispositivo, red, dataset y región representativos.
Cuándo aparece el elemento principal visible.
Causas frecuentes:
Latencia de interacciones a lo largo de la visita.
Causas:
Movimiento inesperado.
Causas:
Usa percentil 75 de usuarios reales, no solo Lighthouse local.
Lighthouse, DevTools, WebPageTest. Reproducible, útil para diagnosis.
Real User Monitoring, CrUX, analytics de web vitals. Captura dispositivos y redes reales.
Un score alto local no prueba producción. Un field metric malo necesita segmentación por ruta, dispositivo, país y release.
Incluye:
network
+ CDN miss
+ Proxy
+ server cold start
+ auth/data
+ render until shellDiagnóstico:
No sacrifiques seguridad o freshness para bajar TTFB sin comprender el producto.
Una caché con 5% de hits añade complejidad sin beneficio. Mide:
Una key por usuario en contenido poco repetido puede ser peor que una query directa optimizada.
Server Components no vuelven rápida una consulta lenta.
JS → render → useEffect fetch → dataMueve datos iniciales al servidor.
const user = await getUser();
const metrics = await getMetrics();
const alerts = await getAlerts();Paraleliza si son independientes o separa boundaries.
chunk → component → data requestInicia datos antes o usa Server Components.
Visualiza el waterfall, no adivines.
Permite enviar shell antes de contenido lento. Mide:
No coloques el elemento principal en una region que llega tarde solo para mejorar TTFB.
Beneficios:
Riesgos:
Mide bytes de flight/RSC y duración servidor.
Solo Client Components hidratan. Coste depende de:
Mueve interactividad a islands pequeñas, pero no fragmentes una feature coherente en docenas de boundaries con props complejas.
Un render adicional no equivale a DOM o lentitud. Usa React Profiler para commits costosos.
Causas Next-specific:
useSearchParams en árbol amplio.Optimiza después de identificar el commit y la causa.
sizes correcto.preload para LCP.Compara bytes descargados con tamaño renderizado.
next/font.Pueden dominar INP y red. Mide el árbol completo de requests. Estrategias:
lazyOnload.No existe optimización mejor que no cargar un proveedor innecesario.
Acelera navegación, pero consume datos. En links masivos puede generar requests. Mide cache reuse y ancho de banda.
Prefetch por intención para rutas pesadas.
Puede hacer instantánea una navegación repetida. Si stale time es demasiado largo, UX parece rápida pero obsoleta. Rendimiento y consistencia se negocian juntos.
Ejecutar cerca del usuario reduce red, pero si la DB sigue en otra región crea una vuelta larga:
user Bogotá → edge Miami → DB FrankfurtA veces ejecutar cerca de datos es más rápido. Mide la topología completa.
Afectan funciones serverless con dependencias grandes e inicialización pesada.
sharp.Next.js no configura toda la infraestructura automáticamente.
Grandes objetos, caches sin límite y buffers de archivos pueden agotar memoria.
Streaming evita cargar archivos completos. Limita cache cardinality y observa heap/RSS.
En serverless, memory alta también aumenta coste.
Mueve trabajo determinista a build/cache, usa workers/jobs o reduce datos. useMemo cliente no reduce el primer cálculo ni server CPU.
Tablas con miles de filas consumen DOM/layout. Paginación puede ser mejor semántica y operativamente. Virtualización aporta para scroll continuo, pero complica accesibilidad, alturas y navegación.
No virtualices 30 elementos.
Ejemplos:
home LCP p75 < target
checkout INP p75 < target
JS initial per route < budget
RSC payload < budget
DB p95 < budget
cache hit ratio > targetAsigna owner y alerta por release. Los targets dependen del producto; no copies un número sin contexto.
Usa useReportWebVitals o integración de observabilidad:
"use client";
export function WebVitals() {
useReportWebVitals((metric) => {
reportMetric({
name: metric.name,
value: metric.value,
id: metric.id,
route: window.location.pathname,
});
});
return null;
}Samplea, protege privacidad y añade release/device context. No envíes cada evento a una Action costosa.
Síntoma: búsqueda se congela.
Diagnóstico:
Solución posible:
No empezar con useCallback en cada handler.
Sirve datos incorrectos o complica personalización.
Pierde cache.
Complejidad sin evidencia.
No representa usuarios.
Oculta cold starts/fallos.
Cuello real permanece.
Retrasa visibilidad.
Regresión de producto.
Observabilidad, instrumentation y logging convierte métricas, errores y traces en evidencia operativa correlacionada por request y release.