Optimised images and fonts

Next.js · Essentials · 11 min

Images and fonts are the biggest causes of slow loads and layout shift; Next.js fixes both with two components.

`next/image`'s <Image> component extends <img> with automatic optimisation:

  • It serves resized, modern-format (WebP/AVIF) versions for each device size and lazy-loads by default.
  • It requires dimensions to prevent layout shift. Statically imported images (import hero from './hero.jpg') provide width, height and a blur placeholder automatically. Remote images need explicit width and height, or fill to fill a positioned parent (with sizes describing the rendered width).
  • Remote hosts must be allowed in next.config.ts with images.remotePatterns.
  • For the hero image above the fold (your Largest Contentful Paint element), set preload so it loads early; the older priority prop is deprecated in Next.js 16.

`next/font` downloads fonts at build time and self-hosts them with your app, so there are no requests to Google at runtime and no layout shift (it generates fallback metrics):

import { Inter } from 'next/font/google'
const inter = Inter({ subsets: ['latin'] })
<body className={inter.className}>

Use variable: '--font-inter' to expose it as a CSS variable (handy with Tailwind). next/font/local loads font files from your project. Define fonts once in a shared module and reuse them; each call creates a separate font instance.

Example

// next.config.ts
// const nextConfig: NextConfig = {
//   images: { remotePatterns: [new URL('https://images.example.com/**')] },
// }

// app/page.tsx
import Image from 'next/image'
import { Inter } from 'next/font/google'
import hero from './hero.jpg'                 // static import: size known at build time

const inter = Inter({ subsets: ['latin'], variable: '--font-inter' })

export default function Home() {
  return (
    <main className={inter.variable}>
      <Image src={hero} alt="Mountains at dawn" placeholder="blur" preload />
      <Image
        src="https://images.example.com/avatar.png"
        alt="Avatar"
        width={64}
        height={64}                            // required for remote images
      />
    </main>
  )
}

Remember

  • <Image> resizes, converts and lazy-loads; dimensions prevent layout shift
  • Allow remote hosts with images.remotePatterns; use preload for the LCP image
  • next/font self-hosts fonts at build time with zero layout shift

Watch out for

  • Using a remote image URL without width/height (or fill) and without a matching remotePatterns entry, which fails.

Check yourself

  1. When does next/font/google download the font files?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: nextjs.org/docs/app/getting-started/images

Builds on

Unlocks

Nothing builds on this yet.