Guides/Web Development
Web Development9 min read

How to Improve Core Web Vitals in Next.js

Core Web Vitals (LCP, INP, CLS) directly affect your Google search ranking. This guide covers the most impactful optimizations for Next.js apps to hit green scores across all three metrics.

Understanding the Three Core Web Vitals

LCP (Largest Contentful Paint) measures how quickly the main content loads — target under 2.5 seconds. INP (Interaction to Next Paint) measures responsiveness to user interactions — target under 200ms. CLS (Cumulative Layout Shift) measures visual stability — target under 0.1. Check your current scores in Google Search Console or run a Lighthouse audit in Chrome DevTools.

Fix LCP: Optimize Your Hero Image

The hero image is almost always the LCP element. In Next.js, use the built-in Image component with priority prop for above-the-fold images: <Image src="/hero.jpg" priority width={1200} height={630} alt="Hero" />. The priority prop adds a preload link tag. Also serve images in WebP/AVIF format — Next.js Image handles this automatically. Add sizes prop to serve smaller images on mobile.

Fix LCP: Reduce Server Response Time

Slow TTFB (Time to First Byte) prevents LCP from ever being fast regardless of other optimizations. For Next.js apps: use static generation (generateStaticParams) for pages that can be pre-rendered. Use Incremental Static Regeneration (revalidate) instead of always server-rendering. Add a CDN in front of your server. Enable Nginx gzip compression and static asset caching.

Fix CLS: Reserve Space for Dynamic Content

CLS is caused by content that shifts as the page loads. Common causes: images without explicit width/height, fonts that cause FOUT, ads, and embeds. In Next.js: always set width and height on Image components. Use font-display: optional or swap with next/font. Reserve space for any content loaded asynchronously by setting a min-height on its container before it loads.

Fix INP: Reduce JavaScript Execution Time

Slow event handlers cause high INP. Use React.memo and useMemo to prevent unnecessary re-renders. Break long tasks into smaller chunks with setTimeout or scheduler.yield(). Use dynamic imports to code-split large components: const HeavyChart = dynamic(() => import("./HeavyChart"), { ssr: false }). Move expensive computations to Web Workers. Profile with Chrome DevTools Performance tab to find specific bottlenecks.

Fix INP: Optimize Event Handlers

Debounce search inputs and scroll handlers. Avoid synchronous localStorage access in event handlers — it blocks the main thread. Use the useTransition hook in React 18 to mark state updates as non-urgent, keeping the UI responsive during heavy updates: const [isPending, startTransition] = useTransition(); startTransition(() => setSearchResults(results)). This prevents search from blocking typing.

Need Help?

Want this done for you?

Our engineering team handles implementations like this every week. Get a free scoping call — we will tell you exactly what it takes and what it costs.

Book a free call

© 2026 NexWorldTech — Built for Global Dominance.