Skip to main content
Mujtaba Farooq logoMujtaba
Back to BlogFull-Stack Development

Next.js Performance Optimization: A Practical Checklist

Mar 27, 20262 min read
Share:

Start With Measurement, Not Guessing

Before optimizing anything, measure Core Web Vitals (LCP, CLS, INP) on real devices and real network conditions, not just on a fast laptop on office wifi. Lighthouse, the Vercel dashboard, or real-user monitoring all work — the point is having a number before and after any change, so you know whether it actually helped.

Fix Largest Contentful Paint (LCP) First

  • Preload the hero image or primary above-the-fold content explicitly rather than relying on the browser to discover it late
  • Use the Image component for any meaningful image, which handles responsive sizing and modern formats automatically
  • Avoid render-blocking resources before the main content — check for synchronous scripts or unnecessary client-side data fetching gating the initial render

Reduce Unnecessary Client-Side JavaScript

Every component that doesn't need interactivity should be a Server Component, not a Client Component. This is the single highest-leverage architectural decision in the App Router model — Client Components ship their code to the browser; Server Components don't. Auditing which components actually need the "use client" directive versus which have it out of habit often reveals significant unnecessary JavaScript.

Audit Your Data Fetching Waterfall

Sequential data fetches — where one request waits for another to finish before starting — silently add up to slow page loads. Use parallel data fetching wherever requests don't actually depend on each other's results, and check whether your loading states reflect genuine dependencies or just convenient code structure.

Cache Aggressively, Invalidate Precisely

Next.js's caching layer (fetch caching, route segment caching, the Data Cache) can dramatically reduce redundant work, but misconfigured caching causes stale data bugs that erode trust in the system. Be explicit about cache duration and use targeted revalidation (revalidatePath, revalidateTag) rather than disabling caching broadly out of caution.

Check Bundle Size Regularly

Run a bundle analyzer periodically, not just once at project start. Dependencies accumulate over a project's life, and a library imported for one small feature can silently add hundreds of kilobytes if it's not tree-shaken properly. optimizePackageImports and dynamic imports for rarely-used heavy components both help here.

Don't Over-Optimize Routes That Don't Matter

Spend optimization effort proportional to traffic and user impact. The admin settings page visited by three internal users doesn't need the same performance budget as your homepage or your highest-traffic product page. Profiling tells you where the actual user impact is — optimize there first.

A Realistic Checklist Order

  • Measure current Core Web Vitals on real conditions
  • Fix LCP issues on your highest-traffic pages
  • Audit Server vs. Client Component split for unnecessary client JS
  • Parallelize data fetching waterfalls
  • Review and tighten caching configuration
  • Run a bundle analysis and address the largest unnecessary dependencies

Work through this roughly in order — fixing LCP on a page that ships 800KB of unnecessary JavaScript will have limited impact until the JavaScript issue is also addressed, and vice versa.

Mujtaba Farooq

Mujtaba

Senior Full-Stack Software Engineer with 7+ years of experience building scalable FinTech and SaaS platforms.

Next.jsReact