Back to Blog
Next.js 7 min readJul 2025

How to Build a High-Performance Next.js Website in 2025

Most "slow Next.js site" complaints aren't a framework problem — they're a handful of default decisions left unmade. Here's the checklist I run through on every project, in the order it actually moves the needle.

1. Let the server render what the server can render

App Router components are Server Components by default. The single biggest performance mistake I see is a stray "use client" at the top of a file that didn't need it, which drags every child component into the client bundle with it. Keep "use client" as low in the tree as possible — usually just the interactive leaf (a button, a form, a dropdown), never the layout or page shell around it.

2. Treat images as a performance budget, not an afterthought

  • Always use next/image, never a raw <img> tag for content images — it handles responsive sizes, lazy loading, and format negotiation automatically.
  • Set formats: ['image/avif', 'image/webp'] in next.config.ts so the browser gets the smallest format it supports.
  • Give every image a real sizes attribute matched to its actual rendered width at each breakpoint — a wrong sizes value silently downloads a larger image than needed.
  • Mark exactly one image priority — normally the LCP element — and nothing else. Marking multiple images priority defeats the purpose.

3. Load fonts without a layout shift

Use next/font instead of a <link> to Google Fonts. It self-hosts the font file (no third-party request), inlines the font-face, and — critically — sets display: swap so text renders in a fallback font immediately instead of staying invisible while the font loads. That one setting is usually the difference between a good and a bad CLS score.

4. Cache aggressively, invalidate deliberately

Static generation (SSG) and Incremental Static Regeneration (ISR) should be your default, not server-side rendering on every request. If a page's data doesn't need to be real-time, generate it at build time and revalidate on a schedule (revalidate: 3600 for hourly, for example) instead of hitting your database on every visit.

5. Measure the three metrics that actually matter

MetricWhat it measuresGood target
LCP (Largest Contentful Paint)How fast the main content appearsUnder 2.5s
INP (Interaction to Next Paint)How responsive the page feels when clicked or tappedUnder 200ms
CLS (Cumulative Layout Shift)How much the page jumps around while loadingUnder 0.1

Run PageSpeed Insights or Lighthouse on the real deployed URL, not localhost — dev-mode builds are unoptimized and will show numbers that don't reflect production. Field data (from real visitors, via Search Console's Core Web Vitals report) is more trustworthy than a single lab run.

The short version

Server Components by default, client components only where you need interactivity, next/image and next/font instead of raw tags, static generation over server rendering wherever the data allows it, and measure against LCP, INP, and CLS on the live URL — not vibes. That combination is what actually produces a 90+ Lighthouse score, consistently, without exotic tricks.

Have a project in mind?

Start a Project