Hvordan du stopper med at gætte dig til performance i Chrome DevTools
De fleste tror en langsom hjemmeside handler om “for meget JavaScript”. Det passer ikke. Jeg har set sider, der føles som sirup, fordi ét billede var gigantisk, eller fordi en font blev hentet på den værst tænkelige måde.
Det er sjældent én magisk årsag. Det er et par små ting, der tilsammen gør oplevelsen træls. Og her er pointen: hvis du ikke har en fast måde at undersøge performance på, så ender du med at gætte og tweake tilfældigt.
Jeg vil vise dig, hvordan du bruger Chrome DevTools som et målebånd, ikke som et kaos-værktøj med 30 faner. Vi bygger en lille, gentagelig proces, du kan køre på alle dine projekter.
Før du åbner DevTools: hvad er det egentlig, der føles langsomt?
Inden du kaster dig over fanen “Performance” og får stress af alle farverne, skal du være lidt kedelig: definer problemet.
Stil to konkrete spørgsmål:
- Hvornår føles det langsomt? Ved første load, ved klik, ved scroll?
- Hvad føles langsomt? At se noget på siden, at kunne klikke, at noget reagerer?
Det kobler vi til nogle Web Vitals-begreber:
- TTFB (Time To First Byte): hvor lang tid går der, før serveren overhovedet svarer.
- LCP (Largest Contentful Paint): hvor lang tid går der, før den største synlige ting er tegnet.
- INP (Interaction to Next Paint): hvor lang tid det føles, før klik og input giver visuelt svar.
Du behøver ikke kunne alle definitioner udenad. Brug dem bare som pejlemærker:
- Høj TTFB → mistanke om server/proxy/database/cache.
- Dårlig LCP → ofte billeder, fonts, CSS eller JavaScript der blokerer rendering.
- Dårlig INP → ofte tung JavaScript eller layoutarbejde ved interaktion.
Hvis du vil have en blød intro til vitals, har jeg også skrevet om det i Core Web Vitals uden panik. Her går vi mere direkte efter værktøjerne.
Lav et fast test-scenarie
Vælg ét scenarie, du vil måle på, fx:
- Åbn forsiden i inkognito, uden cache.
- Åbn produktsiden og klik på “Læg i kurv”.
- Åbn dashboardet efter login.
Det scenarie bruger du hver gang, du tester, både før og efter ændringer. Så har du i det mindste én stabil reference.
Trin 1 – Network: er det serveren, assets eller tredjeparts-ting?
Nu skal vi have DevTools i spil.
Åbn siden, højreklik, vælg “Inspect”. Gå til fanen Network. Genindlæs siden med Ctrl+R eller Cmd+R.
Sådan læser du waterfall uden at blive skør
Når du har kørt en load, vil du se en lang liste af requests. Klik på selve HTML-filen øverst (ofte din / eller index route).
- TTFB: Står som “Waiting (TTFB)” under “Timing”. Er den over ~500 ms på en simpel side, bør du løfte et øjenbryn.
- Content Download: Samme sted. Har mest betydning, hvis du sender meget HTML eller store filer.
- Initiator: I tabeloversigten kan du tilføje kolonnen “Initiator”. Den fortæller, hvad der fik en given request til at ske (HTML, JS-fil, noget andet).
- Priority: Viser, hvad browseren forsøger at hente tidligt. Vigtigt for billeder og fonts over folden.
Prøv nu at sortere efter “Time” og kig på de værste syndere i bunden.
Seks klassiske syndere i Network-fanen
Der er et par ting, jeg ser igen og igen, når en side føles tung. Du kan nærmest lave en lille bingo-plade ud af dem.
1. Gigantiske billeder
Tjek kolonnen “Size”. Finder du billeder på 1-5 MB, har du allerede en gevinst liggende.
- Er billedet større i pixels end det vises på skærmen?
- Bruger du et tungt format (PNG hvor JPEG eller WebP ville være fint)?
Første fix at prøve:
- Resize billedet til max den størrelse, det vises i layoutet.
- Gem som WebP eller AVIF, hvis browser-support passer til dit projekt.
- Brug
<img loading="lazy">til billeder, der ikke er over folden.
2. Webfonts der blokerer tekst
Fonts dukker ofte op som 50-200 KB filer, nogle gange flere.
Hvis du ser font-requests, der først bliver hentet sent, og din tekst er usynlig eller hopper, er det en klar kandidat.
Første fix at prøve:
- Brug
font-display: swap;i din @font-face, så system-font vises, indtil webfonten er klar. - Drop varianter du alligevel ikke bruger (fx 100, 200, 900 vægte).
3. Bundling der blev lidt for vild
Kig efter store JS-filer: typisk app.js, main.[hash].js eller lignende.
Hvis du ser én 1 MB+ bundle, er det værd at overveje, om du kan splitte.
Første fix at prøve:
- Aktiver code splitting i dit build-værktøj (Vite, Webpack, osv.).
- Lazy load ruter eller tunge komponenter, som brugeren ikke altid rammer.
4. Manglende cache
Klik på en JS- eller CSS-fil, se fanen “Headers” og kig under “Response Headers” efter cache-control.
Hvis alt har no-store eller meget lav max-age, tvinger du brugeren til at hente det hele hver gang.
Første fix at prøve:
- Sæt lang cache-tid (fx 1 år) på fingerprintede filer (
main.123abc.jsosv.). - Brug kortere cache på HTML (ofte hvor du styrer opdateringer).
5. Third-party scripts der tager over
Analytics, chat-widgets, A/B-testing osv. dukker ofte op i Network med domæner du ikke selv ejer.
Hvis en tredjeparts-request står og hænger, kan den blokere andre ting eller lægge pres på main thread.
Første fix at prøve:
- Fjern scripts, du ikke bruger aktivt.
- Load dem sent (
defereller via tag manager, der kun kører på visse sider).
6. Redirects og unødige hop
Hold øje med statuskoder: 301, 302. Hvis du ser en kæde som / → /home → /da/home, har du spildtid lige ved start.
Første fix at prøve: peg brugeren direkte på den endelige URL, både i links og i serverkonfiguration.
Trin 2 – Performance-fanen: long tasks og main thread der brænder
Network fortæller dig, hvad der bliver hentet og hvor lang tid det tager. Men det siger ikke noget om, hvad browseren laver på selve maskinen.
Det er her Performance-fanen i DevTools kommer i spil.
Optag en performance-profil
Gør sådan her:
- Åbn DevTools, vælg fanen Performance.
- Sæt evt. “Network” til “Fast 3G” eller “Slow 4G” i toppen, hvis du vil simulere dårligere forbindelse.
- Tryk på runde “Record”-knap.
- Genindlæs siden (eller udfør det scenarie du vil teste, fx klik på en knap).
- Vent et par sekunder efter, tingene føles færdige, og stop så optagelsen.
Nu får du en tidslinje med en masse farvede blokke. Det er her, mange står af. Lad os pille det lidt fra hinanden.
Long tasks: de røde streger du ikke vil se
I toppen af tidslinjen vil du ofte se små røde markeringer. Holder du musen over, står der “Long task”.
En “long task” er, meget forsimplet, et stykke arbejde på main thread, der tager mere end 50 ms. Det betyder, at browseren i den periode har svært ved at reagere på input, animations-frames osv.
Klik på en long task. Nede i “Bottom-Up” eller “Call Tree” kan du se, hvilken kode der bidrager.
// Typisk mønster der giver long tasks
button.addEventListener('click', () => {
// Tung beregning direkte ved klik
for (let i = 0; i < 10_000_000; i++) {
// ... et eller andet
}
// DOM-manipulation i en stor klump
renderBigList();
});
Typiske årsager til long tasks:
- Store loops, der kører synkront.
- Mange DOM-ændringer på én gang.
- Tung JSON-parsing eller data-transformation i browseren.
- Tredjeparts-scripts, der laver meget arbejde i baggrunden.
Første fix at prøve:
- Split lange loops op og brug
requestAnimationFrameellersetTimeouti små bidder. - Batch DOM-opdateringer i stedet for at opdatere 1000 gange i træk.
- Flyt tung behandling til en Web Worker, hvis det giver mening.
Scripting vs rendering vs painting
I toppen af Performance-tidslinjen har du små lagkage-lignende felter med farver:
- Gul → Scripting (JavaScript).
- Lilla/blå → Rendering/layout.
- Grøn → Painting/compositing.
Kig på mønstret:
- Meget gul samlet i klumper → din JavaScript er tung.
- Store lilla blokke, særligt efter DOM-ændringer → layout bliver genberegnet igen og igen.
- Store grønne blokke → tegning af mange elementer, ofte ved animationer eller scroll.
Hvis du fx ser en kæmpe gul blok, hver gang du skriver i et input, er det en indikator på, at du måske laver for meget arbejde på input-eventet.
// Klassisk INP-dræber
input.addEventListener('input', handleSearch);
function handleSearch(e) {
const value = e.target.value;
// Triggerer API-kald og fuld re-render for hvert tastetryk
fetch(`/search?q=${value}`)
.then(res => res.json())
.then(renderResults);
}
Første fix at prøve: brug debounce:
function debounce(fn, delay) {
let id;
return (...args) => {
clearTimeout(id);
id = setTimeout(() => fn(...args), delay);
};
}
input.addEventListener('input', debounce(handleSearch, 250));
Nu får du langt færre lange scripting-perioder ved input, og INP har en chance.
Trin 3 – Memory: hurtig sanity check for lækager
Hvis din side bliver værre og værre, jo længere den er åben, kan du have en memory leak eller lignende.
Chrome har en Memory-fane, som kan meget mere, end vi får brug for her. Vi bruger den bare til en simpel test:
- Åbn fanen Performance.
- Aktiver “Memory”-checkbox i toppen.
- Optag mens du bruger siden som normalt i 20-30 sekunder.
Hvis memory-grafen bare kravler støt opad uden at falde, selvom du går frem og tilbage mellem visninger, kan du have komponenter, event listeners eller data, der aldrig bliver ryddet op.
Typiske kilder:
- Event listeners der bliver tilføjet ved hver render, men aldrig fjernet.
- Globale arrays/objekter, du bare tilføjer til, men aldrig rydder.
- SPA-ruter, der holder referencer til gamle views.
Her giver det mening at dykke mere ned i Chromes egen memory-dokumentation, men ofte kan du komme ret langt bare ved at rydde op i event listeners.
Trin 4 – Verificér dine fixes med samme setup
Performance-arbejde uden måling før/efter er basically religion. Det føles rigtigt, men du ved ikke, om det hjalp.
Gør det her til en vane:
- Notér et par tal før du ændrer noget: TTFB på HTML, LCP fra Performance, evt. INP via Web Vitals extension eller Lighthouse.
- Lav ét fokuseret fix ad gangen (fx optimer hero-billedet).
- Deploy/byg igen.
- Kør samme scenarie, samme Network-throttling, samme enhedstype.
- Sammenlign tal.
Hvis du fx går fra LCP 3,2 s til 1,6 s efter at have gjort hero-billedet mindre og flyttet det direkte ind i HTML-markup, har du en ret klar årsagssammenhæng. Det er også noget, du kan vise i en ansøgning eller til en kollega, i stedet for “jeg tror den er hurtigere nu”.
Hvis du vil kombinere det her med Lighthouse, så brug Lighthouse til overblik og DevTools til selve fejlfindingen. Jeg har det lidt sådan, at Lighthouse er som din karakter i skolen, mens DevTools er dine rettede opgaver.
Der ligger i øvrigt en artikel om netop den kombination i “Core Web Vitals uden panik” og en mere generel fejlfindingstilgang i “Jeg stoler mere på mine logs end på min hukommelse“.
Mini-tjekliste: symptom → årsag → første fix
Her er den lille mentale matrix, jeg selv bruger, når nogen siger “siden er langsom” uden flere detaljer.
1. Siden tager lang tid om overhovedet at begynde at loade
Mest sandsynlige årsag: høj TTFB, serveren svarer langsomt.
Tjek i DevTools:
- Network → klik på HTML-request → “Waiting (TTFB)”.
Første fix at prøve:
- Tænd caching af HTML, hvis indholdet ikke skifter for hvert request.
- Hvis du kører SSR eller et tungt API-kald under render, så cache det resultat.
- Mål database-queries på serveren, hvis du har adgang til logs.
2. Indholdet dukker sent op, men når det først er der, føles siden ok
Mest sandsynlige årsag: tung LCP, ofte billede/font/CSS/JS der blokerer.
Tjek i DevTools:
- Performance → se LCP-markeringslinjen.
- Kig på Network for store filer, der loader før LCP.
Første fix at prøve:
- Optimér størrelsen på det billede der er LCP-elementet.
- Sørg for at CSS til layout er kritisk og loader tidligt.
- Flyt ikke-essentielt JS væk fra initial load (defer/lazy).
3. Siden hakker ved scroll eller animationer
Mest sandsynlige årsag: for meget layout/paint-arbejde per frame.
Tjek i DevTools:
- Performance → optag mens du scroller.
- Kig efter store lilla/grønne blokke, der flugter med scroll.
Første fix at prøve:
- Undgå at ændre layout-egenskaber i scroll-handlers (top, left, width, height).
- Brug
transformogopacitytil animationer. - Reducer antal elementer i DOM, hvis du renderer lister på flere tusinde elementer.
4. Klik og input føles trægt
Mest sandsynlige årsag: long tasks på main thread under interaktion.
Tjek i DevTools:
- Performance → optag mens du klikker eller skriver.
- Kig efter long tasks (røde streger) lige efter interaktion.
Første fix at prøve:
- Debounce input-håndtering.
- Flyt tung logik væk fra selve klik-øjeblikket.
- Prøv at give hurtig visuel feedback først (fx disabled-knap, spinner), og lav derefter det tunge arbejde.
5. Siden bliver langsommere, jo længere den er åben
Mest sandsynlige årsag: memory leak eller tiltagende arbejde, der aldrig ryddes op.
Tjek i DevTools:
- Performance med “Memory” aktiveret → optag 30-60 sekunder.
- Kig om memory-grafen over tid bare vokser og vokser.
Første fix at prøve:
- Ryd op i event listeners ved unmount/destroy.
- Undgå globale arrays, der vokser uden begrænsning.
- Tjek at dit SPA-router-framework faktisk fjerner gamle views.
Når det faktisk er serveren der er langsom
Nogle gange kan du optimere billeder og JavaScript lige så tosset du vil. Hvis TTFB er 2 sekunder, når du sidder på en hurtig forbindelse, har du et serverproblem.
Hvad du måler i DevTools
Igen: Network → HTML-request → “Timing”.
- Blocked/Queueing: tid i kø i browseren (fx for mange parallelle requests).
- DNS Lookup: kan være lidt højt første gang, men bør ikke dominere.
- Initial connection: TCP/SSL handshake, typisk ok.
- Waiting (TTFB): det er her serveren rent faktisk laver arbejde.
Hvis “Waiting (TTFB)” er klart den dominerende del, er det sjældent noget, du fixer i frontend.
Næste skridt på server-siden
Hvis du har backend-adgang:
- Log runtime for vigtige endpoints (fx hvor lang tid database-queries tager).
- Test samme endpoint direkte via et REST-værktøj (fx Postman eller curl), uden hele siten.
- Overvej at cache HTML eller API-respons til de mest besøgte sider.
Hvis du kører på en host som Vercel, Netlify osv., så tjek deres logs og performance-værktøjer. Kombinér det med det du ser i DevTools, så har du både “føles langsom” og “er langsom” dækket.
Afslutning: fra kaos-faner til en fast rutine
Jeg åbnede selv Chrome DevTools Network første gang, fordi en side tog en evighed at loade, og jeg troede, det var “React der var langsomt”. Det viste sig at være ét billede på 7 MB fra en kundes iPhone, der blev vist som logo i headeren. React var uskyldig.
Pointen er: du behøver ikke kunne alle faner og grafer udenad. Hvis du bare holder dig til en simpel rytme – definér problemet, start i Network, kig efter long tasks i Performance, lav ét fix ad gangen og mål før/efter – så er du allerede foran mange, der bare kaster endnu et framework efter problemet.
Næste gang en kollega siger “siden føles tung”, kan du roligt trække DevTools frem, sætte din proces i gang og være den stille person i hjørnet, der faktisk finder årsagen i stedet for at gætte.









1 kommentar