Image Optimization in Next.js: Everything You Should Know (2025 Edition)

Himmat Regar Jun 29, 2025, 10:50 PM
nextjs
Views 233
Blog Thumbnail

Poorly-handled images remain the #1 cause of slow pages and failing Core Web Vitals. In the latest HTTP Archive run (May 2025) images made up 52 % of the median mobile transfer size, and they directly drive the Largest Contentful Paint (LCP) metric that now influences Google search rank. Next.js tackles this problem with a first-class Image Optimization API and the <Image> component.
This guide walks through every feature, configuration option, and gotcha you need to master.


1 — Why use next/image instead of raw <img>?

  • Automatic responsive output — Next.js emits a srcset so each device fetches only the pixels it needs, served in modern formats (AVIF/WebP).

  • Built-in lazy-loading keeps off-screen images out of the critical path, improving LCP.

  • Blur-up placeholders & fixed dimensions prevent Cumulative Layout Shift (CLS).

  • Edge-scaled remote images let you resize anything from S3, a headless CMS, or user uploads on the fly.


2 — Local vs. remote images

import Image from 'next/image'
import hero from './hero.png'          // static import (size auto-detected)

export default function Hero() {
  return (
    <>
      <Image src={hero} alt="Temple courtyard" placeholder="blur" priority />
      <Image
        src="https://cdn.example.com/avatars/jane.jpg"
        alt="Jane avatar"
        width={320}
        height={320}
      />
    </>
  );
}

 

Local imports pick up width/height automatically. Remote URLs need explicit dimensions and must be whitelisted:

// next.config.js
export default {
  images: {
    remotePatterns: [
      { protocol: 'https', hostname: 'cdn.example.com', pathname: '/avatars/**' },
    ],
  },
};

3 — Key props & when to use them

Prop Use it for … Notes
priority Your LCP/hero image Adds <link rel="preload"> + fetchpriority="high" where supported.
fill When the container controls the aspect ratio Parent must be position: relative.
sizes Pair with fill for a proper srcset Example: sizes="(max-width: 768px) 100vw, 50vw".
quality Fine-tune lossy compression (1–100) Default 75 is safe; rarely raise it.
fetchPriority Explicitly set high, low, or auto if you must priority already handles most cases.

4 — Tuning next.config.js

 
export default {
  images: {
    deviceSizes:  [640, 768, 1024, 1280, 1920],
    imageSizes:   [16, 32, 48, 64, 96],
    formats:      ['image/avif', 'image/webp'],  // order = preference
    minimumCacheTTL: 60,                         // seconds in edge cache
    contentDispositionType: 'inline',
    dangerouslyAllowSVG: false,
    unoptimized: false,                          // true opts OUT of all transforms
  },
};

Keep deviceSizes ≤ 25 and imageSizes ≤ 50 to avoid the “Invalid images config” build error.


5 — Custom loaders & CDN integrations

The built-in loader proxies through your Next.js server. If you’d rather offload work to Cloudinary, Imgix, Thumbor, or a bespoke service:

// next.config.js
export default {
  images: {
    loader: 'custom',
    loaderFile: './cloudinary-loader.js',
  },
};

// cloudinary-loader.js
export default function cloudinary({ src, width, quality }) {
  return `https://res.cloudinary.com/demo/image/upload/f_auto,q_${quality||75},w_${width}${src}`;
}

 

You can also pass a loader prop per image if only a few need the custom URL pattern.


6 — Static export caveat (output: 'export')

next export (or output: "export") removes the Node runtime that powers on-demand resizing. The default loader then fails with
“Image Optimization API is not available in export”.
Fixes:

  1. Use a custom loader that returns already-optimized CDN URLs.

  2. Host a lightweight image proxy (Edge Function, Cloudflare Workers, etc.) alongside your static build.


7 — Caching & self-hosting tips

  • Edge cache TTL (minimumCacheTTL) — bump to hours for static product shots to slash origin CPU.

  • Sharp memory limits — for huge source images set NODE_OPTIONS="--max_old_space_size=4096" on your server.

  • OG image generation — Next 15 introduces ImageResponse helpers for dynamic social cards at the edge.


8 — Security best practices

Risk Mitigation
Open redirects / SSRF Use strict remotePatterns instead of wildcard domains.
SVG script injection Keep dangerouslyAllowSVG: false unless you sanitize files.
Bandwidth bombs Define realistic deviceSizes and convert user uploads.

9 — Common runtime errors & quick fixes

Error text (abridged) Cause Fix
image src https://foo not configured Host not whitelisted Add pattern to remotePatterns.
You must provide width and height Remote image missing dimensions Supply them or use a static import.
Image Optimization API is not available in export Default loader + static export Switch to custom CDN loader.

10 — Future-proofing (Next 15 + React 19)

  • AVIF now sits first in the default formats array.

  • priority automatically applies fetchpriority="high" on Chrome 115+ & Safari 17.

  • @vercel/og edge helpers let you create social OG images in TS/JS right beside your route handlers.


11 — Mini case study 📈

Metric Before fix After <Image>
LCP (mobile, P95) 4.2 s 1.6 s
CLS 0.11 0.01
Image transfer size 3 MB 980 KB
Add-to-cart conversions +23 %

The Wisp CMS landing page team migrated to <Image>, enabled AVIF/WebP, and increased edge TTL from 60 s to 1 h.


12 — Workflow tips

  • MDX imports auto-inject dimensions and blur placeholders.

  • Wrap <Image unoptimized> in Storybook for screenshot tests (no remote calls).

  • Run npx @next/codemod next-image-to-remotePatterns when upgrading legacy configs.


13 — Testing & debugging checklist

  1. Lighthouse → ensure LCP element = expected hero image.

  2. WebPageTest filmstrip → blur placeholder vanishes < 0.5 s on slow 3G.

  3. DevTools Network → verify AVIF/WebP Content-Type.

  4. next dev overlay → hover an image to see actual decoded bytes.


14 — Accessibility & SEO

  • Descriptive alt text (or alt="" for decorative images).

  • Generate OG/Twitter cards with @vercel/og.

  • Avoid embedding essential text inside images (search/lang-translate issues).


15 — Launch checklist ✅

  1. Audit every <img>; migrate or justify.

  2. Mark the LCP asset priority.

  3. Define real breakpoint arrays (deviceSizes).

  4. Harden remotePatterns; no wildcards.

  5. Disable SVG unless sanitized.

  6. Prefer AVIF → WebP fallback order.

  7. Raise edge cache TTL for static assets.

  8. Cap user-upload dimensions & convert format.

  9. Add Lighthouse perf guardrails in CI.

  10. Document your image rules for the team.


Wrap-up 🌟

With a single component and a few lines of config, Next.js turns image optimization from a DevOps chore into a first-class developer primitive. Embrace modern formats, leverage edge caching, and your pages will feel instant—keeping Core Web Vitals (and users) happy.

Happy optimizing! 🎉

FAQ — Image Optimization in Next.js (2025)

# Question Quick answer
1 Does next/image support AVIF automatically? Yes. AVIF is now the first format in the default formats array, so modern browsers receive AVIF first and fall back to WebP/PNG if unsupported. You can override the order via images.formats in next.config.js. nextjs.org
2 How do I allow remote images? Add each origin to images.remotePatterns (recommended) or the older images.domains array. remotePatterns lets you match protocol, host and path for tighter security. nextjs.org
3 What happens if I forget width and height on a remote image? Next.js will throw “You must provide width and height” at runtime, because it can’t infer the intrinsic size from a URL alone. Always specify them—or use a static import for local files, which auto-detects size. nextjs.org
4 When should I add the priority prop? Only to the single image that defines your page’s Largest Contentful Paint (hero banner, product photo). It preloads the file and sets fetchpriority="high" on supporting browsers, improving LCP. dev.to
5 Does priority download on every page? No. The prop is per-component. Use it sparingly; unnecessary preloads compete for bandwidth and can slow other resources. dev.to
6 Can I disable optimisation for one image? Yes — pass unoptimized on the <Image> element to serve the file exactly as provided (useful for already-compressed SVG or ICO sprites). nextjs.org
7 What breaks under next export / output: "export"? The default Image Optimisation API needs a Node runtime, so static export fails with “Image Optimization API is not available”. Switch to a custom loader (Cloudinary, Imgix, DIY edge function) or forego optimisation. nextjs.org
8 Does next/image generate files at build time? No. All resizing/transcoding happens on demand the first time an image is requested, then it’s cached at the edge for subsequent hits (cache time = minimumCacheTTL). nextjs.org
9 How do I integrate Cloudinary / Imgix? Set images.loader: "custom" and point loaderFile to a JS module that returns the provider’s URL template, or pass a loader function per image. nextjs.org
10 Is SVG safe to serve through next/image? Only if you set images.dangerouslyAllowSVG: true and sanitise files server-side. SVG can embed scripts, so the flag defaults to false. nextjs.org
11 Why is my console warning about too many breakpoints? deviceSizes is limited to 25 values and imageSizes to 50. Exceeding either triggers an “Invalid images config” build error. nextjs.org
12 Does sizes matter with the fill prop? Absolutely. When you use fill, add a sizes attribute so the browser can choose the correct candidate from the srcset; otherwise it assumes the image is 100 vw and may download an oversized file. nextjs.org

Got another question? Drop it below and I’ll update the list! 🎉


Comments

Please login to leave a comment.

No comments yet.

Related Posts

nextjs-explained-beginners-guide-2025
310 viewsnextjs
Himmat Regar Jun 27, 2025, 10:12 AM

Next.js Explained: A 2025 Beginner’s Guide to the React...

nextjs-markdown-blog-tutorial
319 viewsnextjs
Himmat Regar Jun 27, 2025, 10:18 AM

How to Build Your First Blog Using Next.js and Markdown

nextjs-vs-react-differences
301 viewsnextjs
Himmat Regar Jun 27, 2025, 11:09 AM

Next.js vs React: What’s the Difference and When to Use...

nextjs-file-based-routing-guide
317 viewsnextjs
Himmat Regar Jun 27, 2025, 11:23 AM

Understanding File-Based Routing in Next.js

nextjs-api-routes-backend-functionality
223 viewsnextjs
Himmat Regar Jun 29, 2025, 5:03 PM

How to Use API Routes in Next.js for Backend Functional...

nextjs-incremental-static-regeneration-isr-guide
240 viewsnextjs
Himmat Regar Jun 29, 2025, 5:18 PM

Incremental Static Regeneration (ISR) Explained with Ex...

multi-language-website-nextjs-i18n
112 viewsnextjs
Himmat Regar Jun 30, 2025, 5:14 PM

Building a Multi-Language Website with Next.js 15 & Mod...

nextjs-tailwind-css-perfect-ui-pairing
109 viewsnextjs
Himmat Regar Jun 30, 2025, 5:25 PM

Next.js 15 + Tailwind CSS 4: The Perfect UI Pairing

how-to-create-gmail-account-guide-and-steps
187 viewsMail
Himmat Kumar Nov 4, 2024, 7:46 AM

how to create Gmail account ?

responsive-meta-seo-friendly-markup-2025
443 viewsHTML
Himmat Regar Jun 23, 2025, 4:23 PM

Mastering Responsive Meta & SEO-Friendly Markup in 2025