JavaScript-Optimierung: Leistung, Bundle-Größe und Ladung
JavaScript-Optimierung beeinflusst direkt die Seitengeschwindigkeit und Interaktionsleistung (INP). Dieser Leitfaden behandelt Bundle-Reduzierung, Code Splitting, Lazy Loading und Performance-Techniken.
Aktualisiert:Warum JavaScript-Performance wichtig ist
JavaScript ist die CPU-intensivste Ressource im Browser. Große JS-Dateien erhöhen Parse- und Compile-Zeit und beeinflussen INP (Interaction to Next Paint) negativ.
Typischerweise macht JavaScript 40-60% des Seitengewichts aus. Ungenutztes JavaScript verursacht unnötigen CPU- und Speicherverbrauch.
JavaScript-Optimierung verbessert Core Web Vitals Metriken (insbesondere INP und LCP). Optimiertes JS bietet ein schnelleres und responsiveres Nutzererlebnis.
Bundle-Größe optimieren
Tree Shaking: Ungenutzte Exports entfernen. ES Modules (import/export) verwenden. CommonJS (require) unterstützt kein Tree Shaking.
Bundle-Analyse: Bundle-Inhalt mit webpack-bundle-analyzer oder rollup-plugin-visualizer visualisieren. Identifizieren, welche Bibliotheken am meisten Platz einnehmen.
Alternative Bibliotheken: day.js statt moment.js (2KB vs 300KB), lodash-es oder native methods statt lodash. Große Bibliotheken durch leichtere Alternativen ersetzen.
Dependency Audit: Ungenutzte Abhängigkeiten mit npm ls oder depcheck erkennen. Unnötige Abhängigkeiten aus package.json entfernen.
Code Splitting
Route-basiertes Splitting: Separate Bundle für jede Seite erstellen. Seitenkomponenten mit React.lazy() und Suspense lazy laden.
Komponenten-basiertes Splitting: Schwere Komponenten (Modal, Chart, Editor) in separate Chunks aufteilen. Bei Bedarf mit dynamic import() laden.
Vendor Splitting: node_modules-Abhängigkeiten in separate Vendor-Chunk aufteilen. Vendor-Chunk ändert sich nicht und bleibt im Browser-Cache.
Webpack: Automatisches Code Splitting mit optimization.splitChunks. Vite: Rollups automatisches Code Splitting. Next.js: Automatisches route-basiertes Splitting.
Lazy Loading
Dynamic import(): Modul bei Bedarf laden mit const module = await import('./heavy-module.js');.
Intersection Observer: Komponente laden, wenn sichtbar. Below-the-fold Komponenten mit React.lazy + Intersection Observer lazy laden.
Prefetch und Preload: Nicht-kritische Module im Hintergrund prefetchen. Browser lädt im Leerlauf mit <link rel="prefetch" href="chunk.js">.
React Suspense: Loading State für lazy loaded Komponenten anzeigen mit <Suspense fallback={<Loading />}><LazyComponent /></Suspense>.
Performance-Techniken
Debounce und Throttle: Debounce/Throttle bei Scroll-, Resize- und Input-Events verwenden. Mit Lodash debounce oder native setTimeout implementieren.
Web Workers: Schwere Berechnungen vom Hauptthread trennen. CPU-intensive Arbeit im Hintergrund mit new Worker('worker.js') ausführen.
requestAnimationFrame: Animationen und DOM-Updates mit requestAnimationFrame synchronisieren. 60fps anstreben.
Virtual Scrolling: Nur sichtbare Elemente in großen Listen (1000+ Elemente) rendern. react-window oder vue-virtual-scroller verwenden.
Memoization: Unnötige Berechnungen und Re-Render mit useMemo, useCallback und React.memo verhindern.
Messung und Überwachung
Lighthouse Performance Audit: JavaScript execution time, unused JavaScript und Bundle-Größe Metriken prüfen.
Chrome DevTools Performance Tab: JavaScript execution, Scripting und Rendering Zeiten analysieren. Long tasks und Main Thread Blocking erkennen.
Web Vitals: INP, LCP und CLS Metriken überwachen. Reale Nutzerdaten mit web-vitals Bibliothek sammeln.
Real User Monitoring (RUM): Echte Nutzer-Performance-Daten mit Sentry, Datadog oder New Relic überwachen.