Ottimizzazione JavaScript: Prestazioni, Dimensione del Bundle e Caricamento
L'ottimizzazione JavaScript influisce direttamente sulla velocità di caricamento della pagina e sulle prestazioni di interazione (INP). Questa guida copre la riduzione del bundle, il code splitting, il lazy loading e le tecniche di prestazione.
Ultimo aggiornamento:Perché le prestazioni JavaScript contano
JavaScript è la risorsa che consuma più CPU nel browser. I file JS grandi aumentano il tempo di parse e compile e influenzano negativamente la metrica INP.
Tipicamente JavaScript rappresenta il 40-60% del peso della pagina. Il JavaScript inutilizzato causa consumo inutile di CPU e memoria.
L'ottimizzazione JavaScript migliora le metriche Core Web Vitals (specialmente INP e LCP). Il JS ottimizzato fornisce un'esperienza utente più veloce e reattiva.
Ottimizzazione della Dimensione del Bundle
Tree shaking: Rimuovete gli export inutilizzati. Usate ES modules (import/export). CommonJS (require) non supporta il tree shaking.
Analisi del bundle: Visualizzate il contenuto del bundle con webpack-bundle-analyzer o rollup-plugin-visualizer. Identificate quali librerie occupano più spazio.
Librerie alternative: day.js invece di moment.js (2KB vs 300KB), lodash-es o metodi nativi invece di lodash. Sostituite librerie grandi con alternative più leggere.
Audit delle dipendenze: Rilevate le dipendenze inutilizzate con npm ls o depcheck. Rimuovete le dipendenze inutili da package.json.
Code Splitting
Splitting basato su route: Create bundle separato per ogni pagina. Lazy load i componenti di pagina con React.lazy() e Suspense.
Splitting basato su componenti: Dividete i componenti pesanti (modal, chart, editor) in chunk separati. Caricate on demand con dynamic import().
Vendor splitting: Dividete le dipendenze di node_modules in vendor chunk separato. Il vendor chunk non cambia e rimane nella cache del browser.
Webpack: Code splitting automatico con optimization.splitChunks. Vite: Code splitting automatico di Rollup. Next.js: Splitting automatico basato su route.
Lazy Loading
Dynamic import(): Il modulo viene caricato on demand con const module = await import('./heavy-module.js');.
Intersection Observer: Caricate il componente quando è visibile. Lazy load i componenti below-the-fold con React.lazy + Intersection Observer.
Prefetch e preload: Prefetch i moduli non critici in background. Il browser carica quando inattivo con <link rel="prefetch" href="chunk.js">.
React Suspense: Mostrate lo stato di caricamento per i componenti lazy loaded con <Suspense fallback={<Loading />}><LazyComponent /></Suspense>.
Tecniche di Prestazione
Debounce e throttle: Usate debounce/throttle su eventi scroll, resize e input. Implementate con Lodash debounce o setTimeout nativo.
Web Workers: Separate i calcoli pesanti dal thread principale. Eseguite lavoro intensivo di CPU in background con new Worker('worker.js').
requestAnimationFrame: Sincronizzate animazioni e aggiornamenti DOM con requestAnimationFrame. Puntate a 60fps.
Virtual scrolling: Renderizzate solo gli elementi visibili in liste grandi (1000+ elementi). Usate react-window o vue-virtual-scroller.
Memoization: Prevenite calcoli e re-render inutili con useMemo, useCallback e React.memo.
Misurazione e Monitoraggio
Lighthouse Performance audit: Verificate le metriche di tempo di esecuzione JavaScript, JavaScript inutilizzato e dimensione del bundle.
Chrome DevTools Performance tab: Analizzate i tempi di esecuzione JavaScript, scripting e rendering. Rilevate long tasks e blocco del thread principale.
Web Vitals: Monitorate le metriche INP, LCP e CLS. Raccogliete dati reali degli utenti con la libreria web-vitals.
Real User Monitoring (RUM): Monitorate i dati di prestazione degli utenti reali con Sentry, Datadog o New Relic.