What Lighthouse Measures
Google Lighthouse is an open-source tool built into Chrome DevTools that audits web page performance, accessibility, SEO, and best practices. The performance score (0–100) is a weighted composite of six metrics:
| Metric | Weight | What It Measures | Good Threshold |
|---|---|---|---|
| First Contentful Paint (FCP) | 10% | Time until first text/image renders | < 1.8s |
| Largest Contentful Paint (LCP) | 25% | Time until largest visible element renders | < 2.5s |
| Total Blocking Time (TBT) | 30% | Sum of long task blocking time (>50ms each) | < 200ms |
| Cumulative Layout Shift (CLS) | 25% | Visual stability — unexpected layout shifts | < 0.1 |
| Speed Index (SI) | 10% | How quickly visible content populates | < 3.4s |
TBT and LCP together account for 55% of the score — these are where most optimization effort should focus.
Running Lighthouse
Chrome DevTools: F12 → Lighthouse tab → select "Performance" → Analyze page load. Use incognito mode to avoid extension interference.
CLI (for CI/CD):
npm install -g lighthouse
# Basic run
lighthouse https://your-site.com --output=json --output-path=./report.json
# Emulate mobile (default) or desktop
lighthouse https://your-site.com --preset=desktop
# Run only performance category
lighthouse https://your-site.com --only-categories=performance
PageSpeed Insights: pagespeed.web.dev runs Lighthouse and also shows field data from the Chrome User Experience Report (CrUX) — real user measurements, not lab simulations.
Important: Lighthouse lab scores vary between runs (±5 points) due to network conditions and CPU throttling simulation. Run 3–5 times and use the median. Field data from CrUX is more reliable for tracking trends.
Fixing Common Performance Issues
Largest Contentful Paint (LCP) — 25% of Score
The LCP element is usually the hero image, main heading, or largest above-the-fold block.
Top causes and fixes:
<!-- Problem: Hero image loaded lazily (delays LCP) -->
<img src="hero.jpg" loading="lazy">
<!-- Fix: Remove lazy loading from above-the-fold images -->
<img src="hero.jpg" fetchpriority="high">
<!-- Fix: Preload LCP image in <head> -->
<link rel="preload" as="image" href="hero.jpg" fetchpriority="high">
- Slow server response (TTFB > 600ms): Check hosting, database queries, and CDN configuration. Use
Server-Timingheaders to identify backend bottlenecks. - Render-blocking resources: Move non-critical CSS below the fold with
media="print"or inline critical CSS. Defer non-essential JavaScript withdeferorasync. - Unoptimized images: Use WebP/AVIF formats, serve responsive sizes with
srcset, and compress aggressively.
Total Blocking Time (TBT) — 30% of Score
TBT measures how long the main thread is blocked by JavaScript tasks exceeding 50ms. This directly impacts interactivity.
Top causes and fixes:
// Problem: One massive JS bundle blocks the main thread
<script src="app.bundle.js"></script> // 500KB, parsed in one long task
// Fix: Code-split and load only what's needed
<script type="module" src="critical.js"></script>
<script type="module" src="deferred.js" async></script>
- Third-party scripts: Analytics tags, chat widgets, and ad scripts are the biggest TBT contributors. Audit with Chrome DevTools → Performance → Bottom-Up → Group by Third Party.
- Hydration cost (React/Next.js): Server-render critical content and defer hydration of below-the-fold components.
- Large DOM size: Pages with 1,500+ DOM nodes slow parsing and layout. Simplify component trees and remove hidden elements.
Cumulative Layout Shift (CLS) — 25% of Score
CLS penalizes unexpected visual movement after initial render.
<!-- Problem: Image without dimensions causes layout shift -->
<img src="photo.jpg">
<!-- Fix: Always set width and height (browser reserves space) -->
<img src="photo.jpg" width="800" height="600">
<!-- Fix: CSS aspect-ratio for responsive images -->
<style>
img { aspect-ratio: 4/3; width: 100%; height: auto; }
</style>
- Web fonts: Use
font-display: swapwith size-adjusted fallbacks, orfont-display: optionalto eliminate flash entirely. - Dynamic content injection: Ads, banners, and cookie consent widgets that push content down. Reserve space with
min-heighton containers. - Late-loading CSS: Inline critical styles or preload stylesheet with
<link rel="preload" as="style">.
Score Ranges and What They Mean
| Score | Rating | What It Signals |
|---|---|---|
| 90–100 | Good (green) | Meets Core Web Vitals thresholds; no major issues |
| 50–89 | Needs Improvement (orange) | Some metrics failing; optimization opportunities exist |
| 0–49 | Poor (red) | Significant performance problems affecting user experience |
For SEO: Google uses Core Web Vitals (LCP, CLS, INP) as a ranking signal. Pages that fail CWV can lose ranking to competitors with equivalent content but better performance. The ranking impact is a tiebreaker, not a dominant factor — content relevance still matters most.
Lighthouse in CI/CD
Prevent performance regressions by running Lighthouse on every deploy:
# Lighthouse CI — set performance budgets
npm install -g @lhci/cli
# .lighthouserc.json
{
"ci": {
"assert": {
"assertions": {
"categories:performance": ["error", { "minScore": 0.8 }],
"first-contentful-paint": ["warn", { "maxNumericValue": 2000 }],
"largest-contentful-paint": ["error", { "maxNumericValue": 2500 }],
"cumulative-layout-shift": ["error", { "maxNumericValue": 0.1 }],
"total-blocking-time": ["error", { "maxNumericValue": 300 }]
}
}
}
}
# Run in CI
lhci autorun --collect.url=https://staging.your-site.com
This fails the build if LCP exceeds 2.5s or CLS exceeds 0.1 — catching regressions before production.
Lab vs Field Data
| Lab Data (Lighthouse) | Field Data (CrUX) | |
|---|---|---|
| Source | Simulated on controlled device | Real Chrome users over 28 days |
| Consistency | Varies ±5 points per run | Stable (large sample) |
| Metric | TBT (lab proxy for interactivity) | INP (real user interactivity) |
| Use for | Debugging specific issues | Tracking real user experience |
| Where | DevTools, CLI, PageSpeed Insights | PageSpeed Insights, Search Console |
Lighthouse measures TBT as a lab proxy for responsiveness. In the field, Google uses Interaction to Next Paint (INP) instead — which measures actual user interaction latency. A page can score well in Lighthouse TBT but fail INP if JavaScript blocks specific interactions that lab tests don't trigger.
What OpsBlu Tests
OpsBlu's Phase 6 Lighthouse audit runs headless Chrome against each discovered site, capturing all six performance metrics plus accessibility, SEO, and best practices scores. Results are stored per-domain and surfaced in the audit dashboard with specific fix recommendations for each failing metric.
Next Steps
- Core Web Vitals — deep dive into LCP, CLS, and INP
- Server-Side Tracking — reducing client-side performance overhead from analytics
- Google Lighthouse Documentation — official scoring methodology and audit reference
- web.dev Performance — Google's optimization guides with code examples