Table of Contents
- ⚡ Optimize Images: Use
next/image with priority and correct sizes to improve LCP dramatically.
- ⚡ Reduce Main Thread Blocking: Defer non-critical scripts to lower INP and keep interactions smooth.
- ⚡ Prevent Layout Thrashing: Always provide explicit dimensions for images, ads, and dynamic content.
- ⚡ Audit Regularly: Use tools like Lighthouse and Vercel Analytics to monitor Core Web Vitals in production.
Introduction
Core Web Vitals are critical metrics that Google uses to evaluate user experience and rank search results. As Next.js continues to evolve with the App Router and Server Components, optimizing these metrics requires a deep understanding of how the framework renders pages and delivers assets to the browser.
This post examines how to optimize the three primary Core Web Vitals—Largest Contentful Paint (LCP), Interaction to Next Paint (INP), and Cumulative Layout Shift (CLS)—specifically within a Next.js environment.
Optimizing LCP (Largest Contentful Paint)
LCP measures loading performance. To provide a good user experience, LCP should occur within the first 2.5 seconds of the page starting to load. In Next.js applications, the LCP element is typically a hero image or a large block of text.
The Role of next/image
The Next.js Image component simplifies image optimization. However, misconfiguring it can harm LCP.
Key Best Practices:
- Use the
priority prop: Always add the priority property to your LCP image (such as the hero banner). This tells Next.js to preload the image, preventing it from being lazy-loaded.
- Define explicit
sizes: When using responsive images with fill, provide a sizes attribute. This allows the browser to download the correctly sized image for the viewport, which reduces bandwidth and speeds up rendering.
import Image from 'next/image'
export default function Hero() {
return (
<div className="relative w-full h-[500px]">
<Image
src="/hero-banner.jpg"
alt="Hero Banner"
fill
priority
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
className="object-cover"
/>
</div>
)
}
Improving INP (Interaction to Next Paint)
INP measures responsiveness. It assesses a page's overall responsiveness to user interactions by observing the latency of all click, tap, and keyboard interactions that occur throughout the lifespan of a user's visit.
Minimizing Main Thread Blocking
Next.js React Server Components (RSC) heavily reduce the amount of JavaScript sent to the client. By keeping heavy dependencies on the server, you free up the main thread, which directly improves INP.
Actionable Steps:
- Move logic to the server: Fetch data and render static UI on the server. Only use Client Components (
"use client") for interactive elements.
- Defer non-critical scripts: Use
next/script with strategy="lazyOnload" for third-party scripts (like analytics or chat widgets) that do not need to execute immediately.
Preventing CLS (Cumulative Layout Shift)
CLS measures visual stability. A low CLS ensures that the page does not shift unexpectedly as content loads, preventing users from losing their place or accidentally clicking the wrong button.
Stable Layouts with Next.js
Layout shifts often occur when images, ads, or dynamic fonts load asynchronously without reserved space.
Prevention Techniques:
- Reserve space for dynamic content: If you fetch data client-side, always render a skeleton loader or a placeholder with the exact dimensions of the expected content.
- Explicit image dimensions: When not using
fill, always provide explicit width and height properties to next/image. This allows the browser to reserve the correct aspect ratio before the image downloads.
What This Means for Production
Implementing these performance optimizations yields tangible benefits:
- Better UX: Faster load times and smooth interactions reduce bounce rates.
- Higher Search Rankings: Search engines prioritize fast, stable pages.
- Lower Bandwidth Costs: Optimized images and reduced client-side JavaScript decrease server egress costs.
Monitoring Core Web Vitals in Production
Optimization is not a one-time task; it requires continuous monitoring. In a real-world production environment, lab data (from Lighthouse) is not enough. You need field data—metrics collected from actual users experiencing your application under various network conditions and device capabilities.
Leveraging Vercel Analytics and Speed Insights
If you are hosting your Next.js application on Vercel, enabling Vercel Speed Insights provides a zero-configuration way to track your Core Web Vitals. It injects a tiny script into your application that reports LCP, INP, and CLS back to your dashboard in real time.
- Granular Data: You can segment performance data by page, country, and device type.
- Real-Time Feedback: Immediately see the impact of a deployment on your performance metrics.
To integrate it manually into a custom Next.js server setup, you can use the @vercel/speed-insights package.
Google Search Console and Chrome UX Report (CrUX)
For SEO purposes, the ultimate source of truth is the Chrome UX Report (CrUX). This data is what Google Search uses for ranking.
You should regularly monitor the Core Web Vitals report in Google Search Console.
- It aggregates data over a 28-day window.
- It highlights specific URL groups that are failing the "Good" threshold.
By cross-referencing your Vercel Analytics real-time data with the 28-day CrUX data, you can quickly identify regressions before they impact your search rankings.
Implementing Custom Web Vitals Tracking
If you are using a custom backend or a different analytics provider (like Datadog, Sentry, or Google Analytics 4), Next.js provides a built-in hook called useReportWebVitals.
'use client'
import { useReportWebVitals } from 'next/web-vitals'
export function WebVitals() {
useReportWebVitals((metric) => {
const body = JSON.stringify(metric)
const url = 'https://example.com/analytics'
if (navigator.sendBeacon) {
navigator.sendBeacon(url, body)
} else {
fetch(url, { body, method: 'POST', keepalive: true })
}
})
}
Place this component in your root layout to capture metrics across your entire application. This granular tracking ensures that performance budgets are met and that specific user journeys remain fast and responsive.
Conclusion
Optimizing Core Web Vitals in Next.js requires a deliberate approach to rendering, asset delivery, and interactivity. By utilizing Server Components, correctly configuring next/image, and reserving space for asynchronous content, developers can build applications that deliver excellent user experiences and rank highly in search engines.