#Next.js#React

Core Web Vitals and Frontend Performance Optimization

Core Web Vitals are more than SEO metrics; they quantify real user experience. This article explains what LCP, INP, and CLS measure, why they matter, how to measure them with Lighthouse, real-user data, and PSI, and how to improve images, fonts, JavaScript, layout stability, and interaction responsiveness.

Key Points

  • Topic Focus: Next.js、React
  • Suitable for: indie hackers, full-stack engineers, AI application developers
  • Core value: quickly understand background, practical paths, common pitfalls, and engineering advice
Author @admin·Published July 26, 2026·Updated July 26, 2026

Anyone who has worked in frontend development has probably heard of Core Web Vitals (CWV), but many teams understand them only as "Google's SEO score." That view is incomplete. The real value of CWV is that they turn the subjective question of "does this site feel fast?" into three metrics that can be quantified, monitored, and optimized.

This article explains all three metrics in depth and lists the optimization techniques that actually work in practice.

1. Why Core Web Vitals Deserve Your Attention

There are two equally important reasons.

First, they quantify user experience. In the past, we might say, "This page feels sluggish," but how sluggish is it? How different do 1.8-second and 2.6-second initial loads feel to users? Nobody could say precisely. CWV provides three rulers: loading, responsiveness, and visual stability. One measures "how long until the main content is visible," another measures "how long until something happens after a click," and the third measures "whether content jumps around while you are viewing it." Together, these cover the user's entire perception of whether a site is "fast."

Second, they are a Google ranking signal. CWV officially became part of the Page Experience Signal in 2021 and affects search rankings. In March 2024, INP officially replaced FID as the new responsiveness metric. Many teams still have not reacted, even as rankings have quietly changed.

CWV is therefore not an optional "nice to have." It is a hard requirement where neglect can cost you traffic.

2. The Three Metrics: What They Measure and Their Targets

1. LCP (Largest Contentful Paint)

LCP measures loading performance: the time from when the page starts loading until the largest element in the viewport, usually a hero image, large heading, or video poster, finishes rendering.

  • Target: < 2.5s (reaching this at the 75th percentile is considered "good")
  • Needs improvement: 2.5s – 4.0s
  • Poor: > 4.0s

Why measure the "largest element" instead of onload? Because onload measures when resources have finished downloading, not when users can "see" the main content. A hero image that fills the first screen is the real signal users rely on to decide that "the page has appeared."

2. INP (Interaction to Next Paint)

INP measures responsiveness: the latency of all interactions throughout the page lifecycle, including clicks, keyboard input, and taps, using the worst interaction, strictly speaking P98.

  • Target: < 200ms
  • Needs improvement: 200ms – 500ms
  • Poor: > 500ms

Note that INP measures "all interactions," not just the first input. That is exactly why it replaced FID in March 2024. FID measured only the first click's "first input delay," making it blind to SPAs that are "fast at first but increasingly sluggish afterward." INP evaluates the entire usage experience, making the standard considerably stricter.

The 200ms threshold is also worth remembering: when more than 200ms elapses between a user's click and a visible pixel change, the user can clearly feel the lag.

3. CLS (Cumulative Layout Shift)

CLS measures visual stability: the cumulative score of unexpected element movement throughout the page lifecycle.

  • Target: < 0.1
  • Needs improvement: 0.1 – 0.25
  • Poor: > 0.25

A typical example: you are about to click the "Buy" button when an advertisement suddenly appears above it and pushes the button down, causing you to click the ad instead. CLS penalizes precisely this kind of accidental-click experience.

3. How to Measure: Lab Data vs. Real-User Data

There are two approaches to performance measurement, and you must use them together. Looking at only one can mislead you.

Lab Data: Lighthouse simulations run in a controlled environment with a fixed network and device. The advantages are reproducibility, suitability for CI thresholds, and convenient local debugging. The disadvantage is that it represents "one ideal user," not real users.

Field Data: Reports submitted by real users' browsers and aggregated in the Chrome UX Report (CrUX). This is the data Google uses to calculate rankings. In other words, a Lighthouse score of 100 does not mean your CrUX data is good. The latter determines the ranking signal.

Practical tools:

  • Lighthouse: Built into Chrome DevTools. A run provides Lab Data plus a collection of recommendations. Lighthouse CI can enforce thresholds automatically in CI.
  • The web-vitals library: Google's official JavaScript library. Use import { onINP, onLCP, onCLS } from 'web-vitals' in your code and report real-user data to your own monitoring system, such as Grafana, Sentry, or Datadog. This is the standard way to collect Field Data.
  • PageSpeed Insights (PSI): Enter a URL to get both Lighthouse Lab Data and CrUX Field Data. It is the clearest option for a quick health check.
  • Search Console's "Core Web Vitals" report: Directly identifies which URLs fail in CrUX, grouped by issue type. It is free and authoritative, making it a favorite among SEO teams.

4. LCP Optimization: Make the Main Content Visible Sooner

In 90% of cases, the LCP element is an image, followed by text blocks, background images, and video posters. Optimization focuses on four fronts:

1. Prioritize image loading. The LCP image must use fetchpriority="high", with <link rel="preload" as="image"> when necessary. In React and Next.js projects, never give the LCP image loading="lazy". This is one of the easiest mistakes for beginners to make: lazy-loading the most important image destroys LCP.

2. Choose the right image format and dimensions. WebP and AVIF are 30%–50% smaller than PNG and JPEG, with AVIF delivering even greater savings. Remember to provide a fallback for older browsers that do not support AVIF. Next.js next/image automatically generates a responsive srcset for each device DPR. Use it when appropriate instead of writing <img> manually.

3. Improve server response time (TTFB). TTFB sets the lower bound for LCP; if the server is slow, everything else is futile. Use a CDN, adopt edge rendering such as Next.js Edge Runtime, cache HTML appropriately, and avoid serial API calls for above-the-fold content.

4. Eliminate render-blocking resources. Apply defer or async as appropriate to synchronous CSS and JavaScript that the initial screen does not need. But do not defer critical CSS. Extracting above-the-fold CSS and inlining it into the HTML can significantly reduce LCP.

5. Fonts. System fonts are fastest. When using web fonts, always set font-display: swap to prevent FOIT, where text remains invisible while the font loads, from harming LCP.

5. INP Optimization: Make Interactions Feel Immediate

When INP is high, 99% of the time the main thread is occupied by a Long Task lasting more than 50ms, leaving the user's event handler waiting in the queue. The optimization approach is straightforward:

1. Break up long tasks. Split a synchronous function that runs for 200ms into smaller chunks, then yield the main thread with setTimeout or the more modern scheduler.yield():

js
// Yield the main thread so the browser can process pending input and rendering
await scheduler.yield();

scheduler.yield() is a newer API introduced after 2024. It is more reliable than setTimeout(0), handles priorities better, and now has reasonably good support in mainstream browsers.

2. Reduce JavaScript execution on the main thread. Move expensive computation to a Web Worker. Use virtual scrolling for large React lists with react-virtual or @tanstack/react-virtual. Avoid synchronously running JSON.parse on enormous strings on the main thread.

3. Debounce and throttle. High-frequency events such as scroll, resize, and input must be throttled, and their handlers must remain lightweight. Do not call getBoundingClientRect inside a scroll handler because it forces synchronous layout, causing layout thrashing.

4. Use React's concurrency features. useTransition marks "non-urgent state updates" as low priority so React can respond to user input first:

jsx
const [isPending, startTransition] = useTransition();

function handleSearch(value) {
  startTransition(() => {
    setResults(filterHugeList(value)); // This update will not block user input
  });
}

This is a powerful tool provided by React 18+. It can improve INP immediately in search, filtering, tab switching, and similar interactions.

6. CLS Optimization: Stop the Page from "Jumping"

High CLS almost always means that layout dimensions were not reserved in advance. Follow three strict rules:

1. Images, videos, and iframes must have explicit dimensions. Set width and height, or use CSS aspect-ratio. Next.js next/image requires width and height, or fill with a sized container, specifically to prevent this problem. Once dimensions are known, loading the image only fills the reserved area instead of pushing sibling elements away.

2. Reserve space for advertisements, embeds, and dynamically inserted content. Give ad slots a fixed height before the script returns instead of letting them expand the page afterward. The same applies to embedded Web Components. Third-party widgets are a major source of CLS.

3. Use an appropriate font-loading strategy. Font switching changes text width. With font-display: swap, the system font appears first and is replaced after the web font loads, which can shift the layout. Mitigations include size-adjust, font-display: optional to keep the system font when the web font is not ready, or techniques such as font-matches to align font metrics in advance.

7. Lab Data Is Not Field Data: Remember This

The most common misconception is: Lighthouse scores 100, but Google Search Console still reports problems.

The reason is simple. Lighthouse runs once on one machine over one fixed network and reports an "ideal case." CrUX collects data from real users. Someone may open your page over a 3G network on a five-year-old midrange Android phone, and their LCP may be three times your Lighthouse result.

Therefore, Field Data from CrUX is the ranking signal, while Lab Data is a diagnostic tool. The correct process is:

  1. Start with Field Data in Search Console or PSI to identify which URLs and metrics are failing.
  2. Run Lighthouse and record a Performance trace on those URLs to locate the root cause, such as a slow image or an excessively long task.
  3. After making changes, use the web-vitals library to report and continuously monitor real-user data instead of relying only on Lighthouse.

Enforcing Lighthouse thresholds in CI is a good practice, but do not treat it as proof that "performance is OK."

Summary

  • Each of the three metrics has a distinct role: LCP measures loading, INP measures responsiveness, and CLS measures stability. Their respective targets are 2.5s, 200ms, and 0.1. Remember these three numbers to give your optimization work a clear direction.
  • INP has been the new hard metric since March 2024, replacing FID. It evaluates every interaction, not only the first. SPA teams in particular need to reassess their performance.
  • Lighthouse is the health check; CrUX is the report card. Google rankings use real-user data from CrUX. Fast Lab Data does not mean real users have a fast experience.
  • For the highest ROI, focus on images for LCP, dimensions for CLS, and the main thread for INP.
  • Use tools such as React 18+ useTransition, scheduler.yield(), and next/image. Do not approach performance in 2026 with techniques from 2019.

One final thought: performance optimization is not about turning metrics green; it is about making real users wait one second less. Better CrUX data naturally helps SEO, but more importantly, the person opening your site over 4G on the subway has one less reason to swear today.

Related

Related Content