Performance Isn’t an Afterthought
One of the biggest selling points of Next.js is performance out of the box. But “out of the box” only gets you so far. The difference between a good Next.js app and a great one often comes down to intentional decisions about images, fonts, rendering strategy, and code splitting. Let’s walk through the highest-impact optimisations available to you in 2026.
Image Optimisation with next/image
The next/image component is arguably the most impactful single change you can make to a content-heavy site. It handles lazy loading, format conversion (WebP, AVIF), responsive sizing, and prevents cumulative layout shift (CLS) โ all automatically.
import Image from "next/image";
<Image
src="/hero.jpg"
alt="Hero image"
width={1200}
height={630}
priority // Preload above-the-fold images
/>
Key tips: always set width and height to prevent layout shift, use priority on above-the-fold images, and use the sizes prop for responsive images to ensure the browser downloads the right size.
Font Optimisation with next/font
Custom fonts are a common source of layout shift and slow renders. next/font solves this elegantly โ fonts are self-hosted, preloaded, and injected with zero layout shift using a CSS fallback that matches the font metrics:
import { Inter, Geist_Mono } from "next/font/google";
const inter = Inter({
subsets: ["latin"],
display: "swap",
variable: "--font-inter",
});
export default function RootLayout({ children }) {
return (
<html className={inter.variable}>
<body>{children}</body>
</html>
);
}
Strategic Rendering: Know What to Static, Dynamic, and Stream
The single most impactful performance decision you make in Next.js is the rendering strategy for each route:
- Static (SSG) โ generate at build time. Fastest possible delivery, served from the edge. Use for marketing pages, blog posts, documentation.
- Incremental Static Regeneration (ISR) โ static, but regenerated on a schedule. Use for content that changes occasionally โ product listings, news articles.
- Dynamic (SSR) โ rendered per request. Use for user-specific pages, shopping carts, dashboards.
- Streaming โ progressive SSR with Suspense. Use when some data is slow โ stream the fast parts, suspend the slow ones.
Code Splitting and Lazy Loading
Next.js splits your bundle by route automatically, but you can go further with dynamic imports for heavy components that aren’t needed immediately:
import dynamic from "next/dynamic";
const HeavyChart = dynamic(() => import("./HeavyChart"), {
loading: () => <p>Loading chart...</p>,
ssr: false, // Skip SSR for browser-only components
});
This is particularly useful for third-party libraries like charting tools, rich text editors, and map components that add significant weight to your bundle.
Measuring What Matters
Use the built-in Next.js analytics and Vercel Speed Insights to track Core Web Vitals in production โ LCP, FID/INP, and CLS. These are the metrics Google uses for ranking, and they’re the most user-visible aspects of performance. Don’t optimise in the dark; measure first.
Wrapping Up
Performance optimisation in Next.js is a series of deliberate choices โ the right image component, the right font loading strategy, the right rendering model for each route, and targeted lazy loading. None of it is complicated individually. The skill is knowing which lever to pull for which situation.

Leave a Reply
You must be logged in to post a comment.