JavaScript bundle-optimering — Code splitting, tree shaking og analyse
JavaScript er dyrt: download, parse, kompilering og eksekvering. Code splitting sender kun den nødvendige kode til brugeren. Tree shaking fjerner ubrugt kode. Bundle-analyse afslører hvad der fylder.
JavaScript er den dyreste ressource per byte på nettet: det skal downloades, dekomprimeres, parses, kompileres og eksekveres — alt på main thread. Et 500 KB JavaScript-bundle kan blokere interaktivitet i 2-5 sekunder på en middel Android-telefon. Bundle-optimering handler om at sende så lidt JavaScript som muligt, og kun det der er nødvendigt.
Tree shaking
Tree shaking er bundlerens evne til at fjerne ubrugt kode (dead code elimination). Det kræver ESM-imports (ikke CommonJS require):
// ✅ Tree shakeable — kun `formatDate` inkluderes i bundle
import { formatDate } from './utils';
// ❌ Ikke tree shakeable — hele utils-modulet inkluderes
const utils = require('./utils');
Mange npm-pakker eksponerer ikke tree-shakeable ESM. lodash er et klassisk eksempel — import _ from 'lodash' inkluderer hele biblioteket (70+ KB). Alternativet: import debounce from 'lodash/debounce' eller lodash-es.
Sidecar bundles: Vite og Rollup er fremragende til tree shaking af ESM. Webpack kræver mode: 'production' og sideEffects: false i package.json for optimal tree shaking.
Code splitting
Code splitting opdeler ét monolitisk bundle i chunks der loades on-demand:
Route-baseret splitting (React, Next.js):
// React.lazy — chunk loades kun når komponenten renderes
const CheckoutPage = React.lazy(() => import('./CheckoutPage'));
const BlogPost = React.lazy(() => import('./BlogPost'));
Dynamiske imports (alle bundlers):
// Kode loades kun ved klik
button.addEventListener('click', async () => {
const { initChart } = await import('./chart-library');
initChart(data);
});
Vendor splitting — adskil tredjeparts-biblioteker fra applikationskode. Biblioteker ændres sjældnere og caches længere:
// vite.config.js
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
charts: ['chart.js'],
}
}
}
}
Bundle-analyse
Webpack Bundle Analyzer visualiserer hvad der fylder:
npm install --save-dev webpack-bundle-analyzer
# Kør med npx webpack-bundle-analyzer stats.json
Vite bundle visualizer:
npx vite-bundle-visualizer
source-map-explorer analyserer en compiled bundle via source maps:
npx source-map-explorer dist/main.js
Kig efter: duplikeret kode, unødvendigt store biblioteker, og kode der burde lazy-loades.
Komprimering
Alle moderne servere og CDN’er understøtter komprimering. Gzip reducerer typisk JavaScript med 60-70%. Brotli reducerer 15-25% mere end Gzip for tekstfiler:
# Nginx — aktiver Brotli og Gzip
brotli on;
brotli_comp_level 6;
gzip on;
gzip_types text/javascript application/javascript;
Vite og Webpack genererer .gz og .br filer ved build — serveren sender den komprimerede version automatisk.
Moderne JavaScript med browsermål
Bundling til ES2015 (default for mange tools) inkluderer polyfills der er unødvendige for moderne browsere. Specificér et moderne browsermål for at eliminere unødvendige polyfills:
// vite.config.js
build: {
target: 'es2020'
}
// .browserslistrc — moderne browsere only
last 2 Chrome versions
last 2 Firefox versions
last 2 Safari versions
En moderne target reducerer typisk bundle-størrelse med 10-20% ved at eliminere transpilerings-overhead.
Import cost og editor-integration
VS Code extension Import Cost viser størrelsen af hvert import direkte i editoren — tidlig feedback inden bundling. Det er det nemmeste tool til at fange dyre biblioteker før de når produktion. → Denne artikel er en del af Web Performance — Core Web Vitals og teknisk hastighed.
Andre artikler i samme emne
- API — Hvad er API og hvad betyder det for SEO?
- Browser rendering pipeline — Fra HTML til pixels
- Client-side rendering — CSR og SEO-udfordringer
- CSS containment — Isolér rendering og accelerér layout
- DOM — Document Object Model og JavaScript-rendering
- Google Tag Manager — Tag-håndtering og SEO-tracking
- Hydration — SSR og client-side JavaScript kombineret
- JavaScript — Hvad er JavaScript og hvad betyder det for SEO?
- JavaScript og crawling — Hvad Googlebot ser og ikke ser
- JavaScript Rendering og SEO — Hvad Googlebot ser
- JavaScript SEO — Hvad Googlebot kan og ikke kan
- JavaScript-debugging til SEO — Find rendering-problemer
- JavaScript-rendering fejl — Når Googlebot ikke ser dit indhold
- Kritisk renderingsti — Hvad browseren gør før du ser noget
- Next.js og SEO — Server-side rendering og SEO
- Prerendering — Forhåndsrenderet HTML til crawlere
- React og SEO — JavaScript-rendering og søgesynlighed
- Rendering — Hvad Googlebot ser efter JavaScript-rendering
- Scripts og SEO — render-blocking, async og defer
- Server-side rendering — SSR og fordele for SEO
- Service Workers — Offline caching og PWA performance
- Static site generation — SSG og SEO-fordele ved statiske sider
- Web Components og SEO — Custom elements og søgesynlighed
- Web Workers — Parallel JavaScript uden main thread-blokning
Ofte stillede spørgsmål
- Hvad er forskellen på code splitting og tree shaking?
- Code splitting opdeler bundlet i chunks der loades on-demand — brugere downloader kun kode til de sider de besøger. Tree shaking fjerner ubrugt kode fra bundlet ved build-time — hvis du importerer én funktion fra et bibliotek, inkluderes kun den funktion. De er komplementære: tree shaking reducerer chunk-størrelse, code splitting reducerer hvad der loades.
- Hvad er et godt JavaScript-budget for mobilbrugere?
- Google anbefaler under 150 KB komprimeret JavaScript for den kritiske eksekverings-sti (kode der kræves for at siden er interaktiv). Total JavaScript-budget varierer med kontekst, men 300-400 KB komprimeret er en praktisk grænse for de fleste sites. Husk at 300 KB komprimeret JavaScript kan være 1 MB+ ukomprimeret eksekvering.
- Hvordan analyserer jeg hvad der fylder i mit JavaScript-bundle?
- Bundle-analyse kræver et visualiseringsværktøj der viser bundle-indholdet som et interaktivt treemap. Til Vite bruges vite-bundle-visualizer eller rollup-plugin-visualizer. Til Webpack bruges webpack-bundle-analyzer. Source map explorer analyserer den producerede kode via source maps. Typiske synder: store tredjeparts-biblioteker (moment.js, lodash) der importeres i sin helhed, duplicate dependencies og vendor chunks der er for store til at cache effektivt.
- Hvad er dynamic import og hvornår bør det bruges?
- Dynamic import (import()) er JavaScript-syntaks der loader et modul asynkront og on-demand frem for ved startup. Det er mekanismen bag route-based code splitting i frameworks og lazy-loading af komponenter. Brug dynamic import til kode der kun behøves ved brugerinteraktion (fx en modal, en chart-komponent eller et rigt tekstfelt), kode der kun bruges på specifikke sider, og store biblioteker som kun en lille del af brugerne når. Det reducerer initial bundle-størrelse og forbedrer Time to Interactive.
- Hvad er preload og prefetch til JavaScript og hvornår bruges hvad?
- Preload (<link rel=preload as=script>) fortæller browseren at fetche en ressource med høj prioritet — bruges til scripts der er kritiske for sideindlæsning men opdages sent i HTML. Prefetch (<link rel=prefetch>) fetcher ressourcer med lav prioritet til fremtidig brug — bruges til scripts der sandsynligvis behøves på næste side i brugerens navigation. For JavaScript-chunks: brug preload til kritisk JavaScript der er nødvendigt for den aktuelle sides interaktivitet, og prefetch til route-chunks for sandsynlige næste sider.
Placering i ordbogen
- API — Hvad er API og hvad betyder det for SEO?
- Browser rendering pipeline — Fra HTML til pixels
- Client-side rendering — CSR og SEO-udfordringer
- CSS containment — Isolér rendering og accelerér layout
- DOM — Document Object Model og JavaScript-rendering
- Google Tag Manager — Tag-håndtering og SEO-tracking
- Hydration — SSR og client-side JavaScript kombineret
- JavaScript — Hvad er JavaScript og hvad betyder det for SEO?
- JavaScript og crawling — Hvad Googlebot ser og ikke ser
- JavaScript Rendering og SEO — Hvad Googlebot ser
- JavaScript SEO — Hvad Googlebot kan og ikke kan
- JavaScript-debugging til SEO — Find rendering-problemer
- JavaScript-rendering fejl — Når Googlebot ikke ser dit indhold
- Kritisk renderingsti — Hvad browseren gør før du ser noget
- Next.js og SEO — Server-side rendering og SEO
- Prerendering — Forhåndsrenderet HTML til crawlere
- React og SEO — JavaScript-rendering og søgesynlighed
- Rendering — Hvad Googlebot ser efter JavaScript-rendering
- Scripts og SEO — render-blocking, async og defer
- Server-side rendering — SSR og fordele for SEO
- Service Workers — Offline caching og PWA performance
- Static site generation — SSG og SEO-fordele ved statiske sider
- Web Components og SEO — Custom elements og søgesynlighed
- Web Workers — Parallel JavaScript uden main thread-blokning