Optimización de JavaScript: Rendimiento, Tamaño de Bundle y Carga
La optimización de JavaScript afecta directamente la velocidad de carga de la página y el rendimiento de interacción (INP). Esta guía cubre reducción de bundle, code splitting, lazy loading y técnicas de rendimiento.
Actualizado:Por qué importa el rendimiento de JavaScript
JavaScript es el recurso que más CPU consume en el navegador. Los archivos JS grandes aumentan el tiempo de parse y compile y afectan negativamente la métrica INP.
Típicamente JavaScript representa el 40-60% del peso de la página. El JavaScript no utilizado causa consumo innecesario de CPU y memoria.
La optimización de JavaScript mejora las métricas de Core Web Vitals (especialmente INP y LCP). El JS optimizado proporciona una experiencia de usuario más rápida y responsive.
Optimización del Tamaño de Bundle
Tree shaking: Elimine exports no utilizados. Use ES modules (import/export). CommonJS (require) no soporta tree shaking.
Análisis de bundle: Visualice el contenido del bundle con webpack-bundle-analyzer o rollup-plugin-visualizer. Identifique qué bibliotecas ocupan más espacio.
Bibliotecas alternativas: day.js en lugar de moment.js (2KB vs 300KB), lodash-es o métodos nativos en lugar de lodash. Reemplace bibliotecas grandes con alternativas más ligeras.
Auditoría de dependencias: Detecte dependencias no utilizadas con npm ls o depcheck. Elimine dependencias innecesarias de package.json.
Code Splitting
Splitting basado en rutas: Cree bundle separado para cada página. Lazy load componentes de página con React.lazy() y Suspense.
Splitting basado en componentes: Divida componentes pesados (modal, chart, editor) en chunks separados. Cargue bajo demanda con dynamic import().
Vendor splitting: Divida dependencias de node_modules en vendor chunk separado. El vendor chunk no cambia y permanece en el cache del navegador.
Webpack: Code splitting automático con optimization.splitChunks. Vite: Code splitting automático de Rollup. Next.js: Splitting automático basado en rutas.
Lazy Loading
Dynamic import(): El módulo se carga bajo demanda con const module = await import('./heavy-module.js');.
Intersection Observer: Cargue el componente cuando sea visible. Lazy load componentes below-the-fold con React.lazy + Intersection Observer.
Prefetch y preload: Prefetch módulos no críticos en segundo plano. El navegador carga cuando está inactivo con <link rel="prefetch" href="chunk.js">.
React Suspense: Muestre estado de carga para componentes lazy loaded con <Suspense fallback={<Loading />}><LazyComponent /></Suspense>.
Técnicas de Rendimiento
Debounce y throttle: Use debounce/throttle en eventos de scroll, resize e input. Implemente con Lodash debounce o setTimeout nativo.
Web Workers: Separe cálculos pesados del hilo principal. Ejecute trabajo intensivo de CPU en segundo plano con new Worker('worker.js').
requestAnimationFrame: Sincronice animaciones y actualizaciones del DOM con requestAnimationFrame. Apunte a 60fps.
Virtual scrolling: Renderice solo elementos visibles en listas grandes (1000+ elementos). Use react-window o vue-virtual-scroller.
Memoization: Prevenga cálculos y re-renders innecesarios con useMemo, useCallback y React.memo.
Medición y Monitoreo
Lighthouse Performance audit: Verifique métricas de tiempo de ejecución de JavaScript, JavaScript no utilizado y tamaño de bundle.
Chrome DevTools Performance tab: Analice tiempos de ejecución de JavaScript, scripting y rendering. Detecte long tasks y bloqueo del hilo principal.
Web Vitals: Monitoree métricas INP, LCP y CLS. Recopile datos de usuarios reales con la biblioteca web-vitals.
Real User Monitoring (RUM): Monitoree datos de rendimiento de usuarios reales con Sentry, Datadog o New Relic.