Website Performance Audit (Lighthouse/PageSpeed)
Lighthouse is an automated audit tool from Google. Runs in Chrome DevTools, CLI, or via PageSpeed Insights API. Produces synthetic measurements and outputs score 0–100 across four categories: Performance, Accessibility, Best Practices, SEO. Performance audit is not just getting a number, but understanding improvement priorities and reproducing measurements consistently.
Measurement Methodology
Lighthouse synthetic tests emulate Moto G4 on 4G with 4x CPU throttling. This is median mobile device — on desktop numbers will be better. For audit it's important to:
- run in incognito without extensions (extensions affect metrics)
- do 3–5 runs and take median (Lighthouse is unstable ±10–20 points)
- compare with competitors using same methodology
# Lighthouse CLI — more stable than DevTools (no other tabs)
npm install -g lighthouse
# 3 runs, take median
for i in 1 2 3; do
lighthouse https://mysite.ru \
--output json \
--output-path "run-$i.json" \
--chrome-flags="--headless" \
--throttling-method=simulate \
--preset=mobile
done
Key Metrics and Weights
| Metric | Weight in score | What it measures |
|---|---|---|
| LCP | 25% | Loading of largest element |
| TBT (Total Blocking Time) | 30% | Main thread blocking time |
| CLS | 25% | Layout shifts |
| FCP | 10% | First content render |
| Speed Index | 10% | Visual fill speed |
TBT has highest weight and correlates with INP in real conditions. Sites with large JS bundle without code splitting always have high TBT.
Audit Structure
Stage 1 — Resource Inventory
Lighthouse → Network → check waterfall:
- Render-blocking resources (red rows): CSS without
media, JS withoutdefer/async - Time to First Byte (TTFB) — if > 600ms, server problem
- Page size: HTML > 100KB, JS > 300KB (unparsed), images without WebP
Stage 2 — LCP Element
Lighthouse specifies concrete DOM element for LCP. Common issues:
<!-- Problem: lazy-loading on LCP element -->
<img src="hero.jpg" loading="lazy" ...>
<!-- Fix: eager + fetchpriority -->
<img src="hero.webp" loading="eager" fetchpriority="high"
width="1200" height="500" alt="Hero">
If LCP is CSS background image, Lighthouse doesn't see it as img. Solution: switch to <img> or add <link rel="preload">:
<link rel="preload" as="image"
href="/images/hero.webp"
imagesrcset="/images/hero-400.webp 400w, /images/hero-800.webp 800w, /images/hero.webp 1200w"
imagesizes="100vw">
Stage 3 — TBT and Long Tasks
Lighthouse → View Treemap → shows bundle by size
DevTools → Performance → Long Tasks (red bars > 50ms)
Bundle analysis:
# webpack-bundle-analyzer
npm run build -- --profile
npx webpack-bundle-analyzer dist/stats.json
Typical culprits: moment.js (67KB), lodash without tree-shaking, full import import * as Icons from 'react-icons'.
Stage 4 — CLS
Layout shift causes:
- images without
width/height - dynamically inserted banners/ads
- fonts with FOUT (Flash of Unstyled Text)
- skeleton screens with incorrect sizes
Diagnostics via DevTools → Rendering → Layout Shift Regions (highlights in green).
PageSpeed Insights API
For automatic monitoring after deploy:
PSI_KEY="YOUR_GOOGLE_API_KEY"
URL="https://mysite.ru/"
curl -s "https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=${URL}&key=${PSI_KEY}&strategy=mobile" | \
jq '{
lcp: .lighthouseResult.audits["largest-contentful-paint"].displayValue,
tbt: .lighthouseResult.audits["total-blocking-time"].displayValue,
cls: .lighthouseResult.audits["cumulative-layout-shift"].displayValue,
score: .lighthouseResult.categories.performance.score
}'
PageSpeed Insights uses CrUX data (Chrome User Experience Report) if page has sufficient traffic — this is real user data, more valuable than synthetic.
Task Prioritization
After audit, improvements ranked by impact/effort:
Quick Wins (1–2 hours each):
- Add
width/heightto all<img>— removes CLS - Add
deferto non-critical scripts — reduces TBT - Enable gzip/brotli on server — reduces transfer size
- Add
font-display: swap— reduces LCP if font is culprit
Medium Level (1–3 days):
- Code splitting for JS bundle — reduces TBT/FCP
- Convert images to WebP — reduces transfer size 25–40%
- Lazy loading for off-screen images — reduces initial load
Major Refactors (1–2 weeks):
- Move heavy widgets from SSR to dynamic loading
- Remove render-blocking CSS (inline critical CSS)
- Replace heavy libraries with lightweight alternatives
Audit Timeline
Full audit (Lighthouse, DevTools trace, bundle analysis, CrUX data, prioritized task list): 1–2 days. For large sites with multiple page types (home, catalog, product, checkout) — 2–3 days.







