Shipping a web application without measuring its quality is guessing. Lighthouse is Google’s open-source auditing tool that scores any web page across four categories: performance, accessibility, best practices, and progressive web app compliance. It runs in Chrome DevTools, as a Node CLI, or inside a CI pipeline, and it returns a detailed report with exactly what to fix and why.
How Lighthouse scores web applications
Lighthouse loads the page in a controlled environment, simulates a mid-tier mobile device on a throttled connection, and runs dozens of audits. The performance score is a weighted blend of six metrics where LCP and TBT carry the most weight. A single render-blocking resource or an unoptimized image can drop the score by 20 points.
npx lighthouse https://example.com \
--output=json \
--output-path=./report.json \
--chrome-flags="--headless"
The JSON output is machine-readable, which makes it trivial to parse in scripts or store for historical comparison across deployments.
Fixing the most common warnings
Certain issues appear on nearly every React and Next.js project. Third-party scripts are the worst offenders for render-blocking. Using next/script with afterInteractive ensures analytics and tracking code doesn’t compete with critical rendering.
import Script from 'next/script';
export function Analytics() {
return <Script src="https://analytics.example.com/script.js" strategy="afterInteractive" />;
}
Web fonts cause layout shift and block text rendering. font-display: swap shows fallback text immediately, and unicode-range limits the download to the character set actually used. Together they eliminate most font-related CLS.
@font-face {
font-family: 'Inter';
src: url('/fonts/inter.woff2') format('woff2');
font-display: swap;
unicode-range: U+0000-00FF;
}
Unoptimized images are the single biggest drag on performance scores. The next/image component handles lazy loading, responsive sizing, and format conversion automatically. Serving images in AVIF and WebP through Next.js config is the highest-impact optimization Lighthouse consistently flags.
const nextConfig: NextConfig = {
images: {
formats: ['image/avif', 'image/webp'],
deviceSizes: [640, 828, 1200, 1920],
},
};
Integrating Lighthouse in CI
Running Lighthouse manually after a deploy is reactive. Integrating it into continuous integration catches regressions before production. Google maintains @lhci/cli, a dedicated package for running Lighthouse in CI environments with assertions and performance budgets.
jobs:
lighthouse:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm ci && npm run build
- name: Run Lighthouse CI
uses: treosh/lighthouse-ci-action@v12
with:
urls: |
http://localhost:3000
http://localhost:3000/blog
budgetPath: ./budget.json
uploadArtifacts: true
Performance budgets turn Lighthouse from a diagnostic tool into a quality gate. The build fails if a page exceeds its JavaScript budget or misses a timing threshold. A bundle over 200 KB on mobile is the most common reason Next.js apps score below 90.
[
{
"path": "/*",
"timings": [
{ "metric": "interactive", "budget": 3500 },
{ "metric": "first-contentful-paint", "budget": 1800 }
],
"resourceSizes": [
{ "resourceType": "script", "budget": 200 },
{ "resourceType": "image", "budget": 300 }
]
}
]
Accessibility audits for frontend developers
Lighthouse’s accessibility score catches issues that affect both users and code quality. Missing alt text, broken heading hierarchy, insufficient color contrast, and missing form labels are flagged with direct DOM references. Lighthouse bundles axe-core under the hood, so fixing its warnings also fixes automated accessibility tests.
A React component that renders a button without an accessible label, or a heading structure that skips from h1 to h3, will fail the audit. These are the same issues that screen readers stumble on and that tools like Playwright’s accessibility testing detect.
Conclusion
A single Lighthouse run is a snapshot. Real value comes from tracking trends across deployments. The difference between a team that consistently ships fast, accessible web applications and one that doesn’t is usually one thing: they measure. Run it on every pull request, enforce budgets, and treat score drops like failing tests.