Web performance
Core Web Vitals, lab vs field data, the common causes and their fixes.
Updated
What web performance means
Performance = how fast the user sees content, how fast the page reacts to their actions and how stable the layout is. It matters directly: every extra second of loading loses users and lowers your Google ranking.
You don't optimize by feel. You measure, find the cause, then fix it — in that order.
What you measure: Core Web Vitals
| Metric | The question | Good | Poor |
|---|---|---|---|
| LCP — Largest Contentful Paint | how long until the main element (hero image, heading) appears? | ≤ 2.5 s | > 4 s |
| INP — Interaction to Next Paint | how fast does the page react to a click / key? | ≤ 200 ms | > 500 ms |
| CLS — Cumulative Layout Shift | how much does content "jump" while loading? | ≤ 0.1 | > 0.25 |
Between them is the "needs improvement" zone. The rendering steps are explained in How the browser renders.
Where you measure
| Type | Tools | What it shows |
|---|---|---|
| lab (simulated) | Lighthouse, DevTools → Performance | reproducible results on your machine — good for debugging |
| field (real users) | Vercel Speed Insights, CrUX, PageSpeed Insights | what real users feel, on their phones — this is what counts |
Common causes and fixes
High LCP
| Cause | Fix |
|---|---|
| a large hero image loaded late | next/image with priority (or fetchpriority="high"), AVIF/WebP, correct size — see Image optimization |
| a slow server | caching ('use cache', CDN), a static / PPR page |
| fonts blocking text | next/font (self-hosted, font-display: swap) |
| lots of JS before content | Server Components, content rendered on the server |
High INP
| Cause | Fix |
|---|---|
| heavy JS blocking the thread on click | split the work, move computation to the server or a Web Worker |
| large React re-renders | see React performance, useTransition |
| a huge bundle | code splitting, next/dynamic, fewer libraries |
High CLS
| Cause | Fix |
|---|---|
| images without dimensions | width + height (or aspect-ratio) — the browser reserves space |
| fonts that change text size | next/font (adjusts the fallback automatically) |
| banners / ads injected above content | reserve the space up front |
| a skeleton of a different size than the content | a skeleton with the same dimensions |
The rules with the biggest impact
- Ship less JavaScript — Server Components by default,
'use client'as low as possible. - Images: dimensions, modern format,
lazybelow the fold,priorityfor the main one. - Cache everything you can: CDN,
'use cache', hashed assets. - Measure on a phone, not on your developer laptop.
Summary
- LCP (loading), INP (responsiveness), CLS (stability) — with clear thresholds.
- Lab for debugging, field for reality.
- Less JS, proper images, caching, reserved dimensions.