Otimização de JavaScript: Desempenho, Tamanho de Bundle e Carregamento
A otimização de JavaScript afeta diretamente a velocidade de carregamento da página e o desempenho de interação (INP). Este guia cobre redução de bundle, code splitting, lazy loading e técnicas de desempenho.
Atualizado em:Por que o desempenho de JavaScript importa
JavaScript é o recurso que mais consome CPU no navegador. Arquivos JS grandes aumentam o tempo de parse e compile e afetam negativamente a métrica INP.
Tipicamente JavaScript representa 40-60% do peso da página. JavaScript não utilizado causa consumo desnecessário de CPU e memória.
A otimização de JavaScript melhora as métricas de Core Web Vitals (especialmente INP e LCP). JS otimizado proporciona uma experiência de usuário mais rápida e responsiva.
Otimização do Tamanho de Bundle
Tree shaking: Remova exports não utilizados. Use ES modules (import/export). CommonJS (require) não suporta tree shaking.
Análise de bundle: Visualize o conteúdo do bundle com webpack-bundle-analyzer ou rollup-plugin-visualizer. Identifique quais bibliotecas ocupam mais espaço.
Bibliotecas alternativas: day.js em vez de moment.js (2KB vs 300KB), lodash-es ou métodos nativos em vez de lodash. Substitua bibliotecas grandes por alternativas mais leves.
Auditoria de dependências: Detecte dependências não utilizadas com npm ls ou depcheck. Remova dependências desnecessárias do package.json.
Code Splitting
Splitting baseado em rotas: Crie bundle separado para cada página. Lazy load componentes de página com React.lazy() e Suspense.
Splitting baseado em componentes: Divida componentes pesados (modal, chart, editor) em chunks separados. Carregue sob demanda com dynamic import().
Vendor splitting: Divida dependências de node_modules em vendor chunk separado. O vendor chunk não muda e permanece no cache do navegador.
Webpack: Code splitting automático com optimization.splitChunks. Vite: Code splitting automático do Rollup. Next.js: Splitting automático baseado em rotas.
Lazy Loading
Dynamic import(): O módulo é carregado sob demanda com const module = await import('./heavy-module.js');.
Intersection Observer: Carregue o componente quando visível. Lazy load componentes below-the-fold com React.lazy + Intersection Observer.
Prefetch e preload: Prefetch módulos não críticos em segundo plano. O navegador carrega quando inativo com <link rel="prefetch" href="chunk.js">.
React Suspense: Mostre estado de carregamento para componentes lazy loaded com <Suspense fallback={<Loading />}><LazyComponent /></Suspense>.
Técnicas de Desempenho
Debounce e throttle: Use debounce/throttle em eventos de scroll, resize e input. Implemente com Lodash debounce ou setTimeout nativo.
Web Workers: Separe cálculos pesados do thread principal. Execute trabalho intensivo de CPU em segundo plano com new Worker('worker.js').
requestAnimationFrame: Sincronize animações e atualizações do DOM com requestAnimationFrame. Mire 60fps.
Virtual scrolling: Renderize apenas elementos visíveis em listas grandes (1000+ elementos). Use react-window ou vue-virtual-scroller.
Memoization: Previna cálculos e re-renders desnecessários com useMemo, useCallback e React.memo.
Medição e Monitoramento
Lighthouse Performance audit: Verifique métricas de tempo de execução de JavaScript, JavaScript não utilizado e tamanho de bundle.
Chrome DevTools Performance tab: Analise tempos de execução de JavaScript, scripting e rendering. Detecte long tasks e bloqueio do thread principal.
Web Vitals: Monitore métricas INP, LCP e CLS. Colete dados de usuários reais com a biblioteca web-vitals.
Real User Monitoring (RUM): Monitore dados de desempenho de usuários reais com Sentry, Datadog ou New Relic.