Skip to content
Sahil Durgia/ full-stack
2 min readNext.js

Next.js Image and Font Optimization: Performance That's On by Default

next/image and next/font aren't convenience wrappers — they fix two of the most common, measurable causes of a bad Core Web Vitals score, automatically.

Next.jsperformanceCore Web Vitals

Two of the most common real-world causes of a poor Largest Contentful Paint (LCP) and Cumulative Layout Shift (CLS) score are unoptimized images and web fonts causing a layout jump when they load. Next.js addresses both by default, not as an opt-in performance feature.

What next/image actually does

A plain `<img>` tag downloads whatever file size and format you gave it, at whatever dimensions the source file happens to be, and reserves no layout space until it loads (a common cause of layout shift). `next/image` serves a correctly sized image for the actual rendered dimensions, automatically converts to modern formats (WebP/AVIF) where the browser supports them, lazy-loads offscreen images by default, and requires `width`/`height` (or `fill`) so the browser can reserve the correct layout space before the image ever downloads — directly preventing the layout-shift problem, not just the file-size problem.

What next/font actually does

A web font loaded via a `<link>` to Google Fonts causes a real, visible problem: text renders in a fallback font first, then "flashes" to the real font once it downloads — a shift that also counts against CLS. `next/font` downloads the font file at build time and self-hosts it from your own domain, eliminating both the extra network request to a third-party font host and, using calculated fallback-font metrics, the visible layout shift when the real font swaps in. This site uses it for exactly that reason — see `docs/00-decisions.md`'s note on self-hosted fonts.

Why "on by default" is the actual point

Both problems are solvable by hand without Next.js — manual image resizing pipelines, careful `font-display` and preload tuning. The realistic outcome on most real projects is that hand-rolled version gets implemented once, imperfectly, and then quietly rots as new images and fonts get added without anyone remembering the original discipline. Making the fast path the *default* path, not an opt-in one a team has to keep re-choosing, is what actually keeps performance good over a project's whole lifetime, not just at launch.

Keep reading
Next: from Create React App to Next.js

Part 7 of the why-Next.js series.