Browser runtime profiling with Chrome DevTools and Core Web Vitals optimization...
This skill provides mastery of Chrome DevTools Performance panel to diagnose and resolve runtime performance issues, including rendering bottlenecks, long tasks that block the main thread, and memory leaks.
Proper setup ensures useful, actionable profiling data.
The flame chart is the primary tool for diagnosing runtime issues. It shows main thread activity over time.
Vertical axis: Call stack depth (top = innermost function) Horizontal axis: Time Colors:
Long Task: Any task that blocks the main thread for > 50ms
Visual indicator: Yellow blocks with a red triangle in the upper right corner
Example:
ββββββββββββββββββββββββββββββββββ
β β² (Long Task) β β Red triangle
β evaluateScript 248ms β β Problem!
β ββ processData β
β ββ heavyCalculation β
ββββββββββββββββββββββββββββββββββ
Impact: Blocks user interactions (scrolling, clicking). Aim for tasks < 50ms.
Solution: Break up work with:
setTimeout for splitting tasksrequestIdleCallback for low-priority workuseTransition for large UI updatesLayout Thrashing: Reading layout properties immediately after changing them, forcing synchronous layout recalculation.
Visual indicator: Multiple purple "Layout" blocks in rapid succession
Example flame chart:
JavaScript
ββ updateElements
ββ element.style.height = '100px' (Write)
ββ Layout (Forced) β Purple block
ββ element.offsetHeight (Read)
ββ element.style.width = '200px' (Write)
ββ Layout (Forced) β Purple block
Solution: Batch reads and writes
// BAD: Layout thrashing
elements.forEach(el => {
el.style.height = el.offsetWidth + 'px' // Read, then write
})
// GOOD: Batch reads, then writes
const widths = elements.map(el => el.offsetWidth) // All reads
elements.forEach((el, i) => {
el.style.height = widths[i] + 'px' // All writes
})
Visual indicator: Wide yellow blocks labeled "Evaluate Script" or "Function Call"
Impact: Delays page interactivity (FID/INP)
Solution:
Visual indicator: Many purple "Recalculate Style" or "Layout" blocks
Causes:
Solution:
transform and opacity for animations (these don't trigger layout)Core Web Vitals are user-centric performance metrics.
Definition: Time until the largest content element is rendered
Target: < 2.5 seconds
Where to Find: "Timings" section, blue "LCP" marker
Common Causes:
Solutions:
<link rel="preload" as="image" href="/hero.jpg">Definition: Time from user interaction to visual response
Target: < 200ms (good), < 500ms (acceptable)
Where to Find: "Experience" section when interacting
Common Causes:
Solutions:
useTransition for non-urgent updatesDefinition: Sum of all unexpected layout shifts
Target: < 0.1
Where to Find: "Experience" section, red "Layout Shift" markers
Common Causes:
Solutions:
font-display: optional or preload fontsReal-time graph of key metrics during interaction.
Identify memory leaks and excessive memory usage.
Detached DOM Nodes: Nodes removed from DOM but still in memory
How to Find:
Common Causes:
Solution:
// BAD: Event listener not removed
useEffect(() => {
window.addEventListener('resize', handleResize)
// Missing cleanup!
}, [])
// GOOD: Cleanup function
useEffect(() => {
window.addEventListener('resize', handleResize)
return () => window.removeEventListener('resize', handleResize)
}, [])
Shows memory allocations over time.
Look for: Steadily increasing allocations (potential leak)
Automated performance audits providing actionable recommendations.
Metrics: LCP, FID, CLS, TTFB, Speed Index Opportunities: Specific optimizations with estimated savings Diagnostics: Issues to investigate Passed Audits: What's working well
Development builds have extra debugging code and are not representative of production performance.
Always profile production builds: npm run build && npm start
Extensions add overhead and can skew results.
Always use incognito mode for profiling.
Your development machine is faster than most user devices.
Always enable CPU and network throttling to simulate real-world conditions.
Seeing a long task isn't enoughβyou must drill down into the flame chart to find the specific function causing the issue.
Profile first, then optimize. Don't guess at what's slow.
| Metric | Good | Needs Improvement | Poor |
|---|---|---|---|
| LCP | β€ 2.5s | 2.5s - 4.0s | > 4.0s |
| INP | β€ 200ms | 200ms - 500ms | > 500ms |
| CLS | β€ 0.1 | 0.1 - 0.25 | > 0.25 |
| Symptom | Likely Cause | Where to Look |
|---|---|---|
| Slow page load | Large bundles, slow server | Network tab, Lighthouse |
| Jank during scroll | Layout thrashing, expensive paints | Flame chart (purple blocks) |
| Slow click response | Long tasks blocking main thread | Flame chart (yellow blocks) |
| Content shifting | Missing image dimensions | Experience section (CLS) |
| Memory increasing | Leaking DOM nodes/listeners | Memory panel (heap snapshots) |
| Slow initial render | Large LCP element, render-blocking | Timings section (LCP) |