Feedback

Core Web Vitals for Next.js

By Christian Schreiber · Updated

Next.js is the framework behind many of the largest brand sites, portals and headless shops we measure. It can render pages on the server, stream HTML, optimize images and fonts, and ship very little JavaScript to the browser. It can also do the opposite: hydrate an entire page of client components, bundle a megabyte of libraries into the first load and render the hero image on the client. Both patterns exist in production, which is why Next.js sites in our data range from the fastest to the slowest on a single platform. This guide shows where Next.js sites stand, why INP is their weak spot, and which framework features change the picture.

From PerfDelta's measurements: 41% of the 529 measured Next.js websites pass all three Core Web Vitals (all measured websites: 49%). 70% have a good LCP, 62% a good INP and 72% a good CLS. All values, other platforms and regions are in the Next.js speed statistics. More in the data section below.

Where Next.js sites stand

In our measurements, Next.js sites pass the Core Web Vitals less often than the average website, and the gap is almost entirely INP. LCP and CLS are often fine; the main thread is not. The data section below shows the current figures, and the Next.js speed statistics page adds page weight, third parties and Lighthouse findings, including a regional comparison for Germany, Austria and Switzerland and the UK. The regional differences are large, which says more about who builds with Next.js in each market than about the framework.

What typically slows Next.js sites down

Hydration of large client-component trees

Server-rendered HTML arrives fast, then React re-runs the component code in the browser to attach event handlers. On a page where most components are client components, hydration is one long task that blocks every tap until it finishes. This is the mechanism behind most poor INP values on Next.js, and it scales with the number of components and the size of their props.

Bundle size

Barrel imports that pull a whole library for one function, UI kits with hundreds of components in the shared chunk, date and charting libraries loaded on every route, and polyfills for browsers nobody uses. Each kilobyte is parsed and executed; see JavaScript execution time and unused JavaScript.

Client-rendered LCP images

A hero image inside a client component that renders after hydration, or a background image set by CSS-in-JS, is invisible to the HTML parser. The browser discovers it late and LCP suffers. Lazy loading applied to the hero by a generic image component makes it worse.

Third-party tags

Enterprise Next.js sites carry tag managers, consent tools, A/B testing and personalization like any other enterprise site, and those scripts compete with hydration for the main thread. The third-party code guide applies in full.

Data fetching on the client

Pages that render a skeleton, then fetch data in useEffect, then render the real content push LCP back by a full round trip and often cause layout shifts when the content arrives.

Fixes inside the framework

  1. Make components server components by default. In the App Router, a component is a server component unless it declares 'use client'. Push the client boundary down to the leaves that need interactivity (a button, a form, a carousel) and keep layout, text and data fetching on the server. Less client code means less hydration and a smaller bundle.
  2. Fix the LCP image with next/image and priority. <Image priority /> renders the hero in the HTML, preloads it, sets fetchpriority="high" and disables lazy loading. Every other image keeps the default lazy loading. Give images explicit dimensions or fill with a sized container to prevent layout shifts.
  3. Use next/font. It self-hosts fonts, preloads them, sets font-display and generates a size-adjusted fallback, which removes font-related CLS and an external origin in one step.
  4. Analyze and split the bundle. Run the bundle analyzer, replace barrel imports with direct imports (or enable the framework's import optimization for large libraries), load heavy components with next/dynamic and ssr: false only where they are truly client-only, and move rarely used routes into their own chunks.
  5. Fetch data on the server. Server components and route handlers fetch during the render, so the HTML arrives complete. Use streaming with Suspense boundaries for slow data so the shell paints first without a client-side waterfall.
  6. Load third-party scripts with next/script. The afterInteractive and lazyOnload strategies keep tags off the critical path; beforeInteractive is for the rare script that must run first, such as a consent manager.
  7. Break up long tasks in client code. Where interactivity remains heavy, yield to the main thread between steps (see JavaScript execution time) and avoid synchronous layout reads in event handlers.
  8. Cache and host close to the audience. Static and incrementally regenerated pages served from the edge keep TTFB low; fully dynamic server rendering on a single region does not.

Measuring the result

Track INP in the field per route, because the home page and a product or article route hydrate very differently. In the lab, watch Total Blocking Time and the main-thread breakdown in Lighthouse; hydration appears as one wide task attributed to the framework chunk. PerfDelta's monitoring shows field INP per URL next to the Next.js median so the effect of a client-boundary refactor is visible within the 28-day window.

Frequently asked questions

Is Next.js bad for Core Web Vitals?

No. The framework offers everything needed to pass them. The sites that fail usually ship large client-component trees and heavy bundles, which the framework allows but does not require.

App Router or Pages Router for performance?

The App Router with server components gives more control over how much JavaScript reaches the browser. A well-built Pages Router site can pass too; the difference is in the defaults, not the ceiling.

Why is INP poor when LCP is good?

Fast HTML from the server gets the content on screen, then hydration and third-party scripts occupy the main thread. The visitor sees the page quickly but cannot interact with it. Reducing client code and breaking up long tasks fixes it.

Does next/image always help?

For the LCP image only with priority; otherwise it lazy-loads the hero and delays LCP. For everything below the fold, the defaults are right.

What PerfDelta's measurements show

41% of the 529 measured Next.js websites pass all three Core Web Vitals (all measured websites: 49%). 70% have a good LCP, 62% a good INP and 72% a good CLS. All values, other platforms and regions are in the Next.js speed statistics.

A Next.js home page transfers 4.1 MB at the median, of which 2.0 MB is JavaScript; the most common Lighthouse finding is render-blocking resources.

Data as of October 16, 2026, recalculated daily. Source: PerfDelta's own measurements (Chrome UX Report and Lighthouse); details in the website speed statistics and the methodology.

Thresholds and sources

Field data rating (Chrome UX Report, 75th percentile):

MetricGoodNeeds improvementPoor
LCP≤ 2.5 s2.5 to 4.0 s> 4.0 s
INP≤ 200 ms200 to 500 ms> 500 ms
CLS≤ 0.10.1 to 0.25> 0.25

Sources:

All sources retrieved on October 9, 2026. Thresholds and documentation change; the linked page is authoritative.

Test your site

Run a free scan to see whether this applies to your pages, on mobile and desktop, with lab and field data side by side.

Run a free test

A free account saves your tests and shows how your values change from one test to the next. Daily monitoring with field data and alerts starts with the Solo plan.

Related audits