Speed on a Next.js site isn't an accident — it's a handful of decisions made in a specific order. This walks through them one at a time, on a single page, so you can see exactly what each one buys you.
Step 1 — Start from a Server Component
Next.js's App Router renders Server Components by default. Leave a page as a Server Component unless it genuinely needs browser-only APIs or interactivity — every "use client" you don't add is JavaScript your visitor never has to download.
Step 2 — Let the framework handle images
next/image generates correctly sized, modern-format images and reserves their layout space automatically, which is most of what prevents Cumulative Layout Shift on a typical page.
import Image from "next/image";
export function Hero() {
return <Image src="/hero.jpg" alt="" width={1600} height={900} priority />;
}
The priority flag matters specifically for whatever image is largest above the fold — it tells the browser to fetch it immediately instead of lazily.
Step 3 — Fetch data on the server, not after mount
An async Server Component can fetch its own data directly and render the result on the first response — no loading spinner, no client-side waterfall.
async function getPosts() {
const res = await fetch("https://api.example.com/posts", { next: { revalidate: 60 } });
return res.json();
}
export default async function BlogPage() {
const posts = await getPosts();
return <PostList posts={posts} />;
}
Step 4 — Measure before you optimize further
Run Lighthouse (or next build's own output) before reaching for anything more advanced. Most performance problems on a fresh Next.js project are one of the three steps above, not a missing exotic optimization.
Step 5 — Deploy and re-check on a throttled connection
A page that's fast on your machine can still be slow on a real visitor's. Test with Chrome DevTools' network throttling set to "Fast 3G" before calling it done.



