Optimizing Images in Next.js 15: Beyond next/image Basics
The next/image component handles the basics, but real-world image optimization requires understanding formats, sizing strategies, and loading patterns.
Every Next.js tutorial shows you the <Image> component and calls it a day. Import, set width and height, done. But if your Largest Contentful Paint is still slow and your image requests are still measured in megabytes, the basics aren't enough.
Here's what image optimization actually looks like in a production Next.js application.
Understanding What next/image Does (and Doesn't Do)
The <Image> component automatically generates multiple sizes via srcset, lazy-loads off-screen images, and serves modern formats (WebP/AVIF) when the browser supports them. What it doesn't do: choose the right sizing strategy for your layout, handle art direction, optimize your loading priority, or prevent layout shift from dynamic content.
Sizing Strategy: fill vs. Fixed Dimensions
The most common mistake is setting explicit width and height on images that should be responsive. If your image fills its container, use the fill prop with a sized parent:
// ❌ Fixed dimensions — breaks on different screen sizes
<Image src={post.coverImage} width={800} height={400} alt={post.title} />
// ✅ Fill mode — responsive, maintains aspect ratio
<div className="relative aspect-video w-full overflow-hidden rounded-lg">
<Image
src={post.coverImage}
alt={post.title}
fill
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
className="object-cover"
/>
</div>
The sizes prop is critical here. Without it, Next.js assumes the image is full viewport width and generates unnecessarily large variants. With proper sizes, a 33vw image on desktop won't load a 1920px version — it'll load ~640px, saving 70%+ bandwidth.
Priority Loading for LCP Images
Your hero image or above-the-fold cover image is almost certainly your LCP element. By default, <Image> lazy-loads everything. Add priority to your LCP image to preload it:
// Hero image — this is the LCP element
<Image
src={article.heroImage}
alt={article.title}
fill
priority
sizes="100vw"
className="object-cover"
/>
// Below-the-fold images — keep default lazy loading
<Image
src={article.inlineImage}
alt="Diagram"
width={600}
height={400}
loading="lazy"
placeholder="blur"
blurDataURL={article.inlineImageBlur}
/>
Only use priority on 1–2 images per page. Marking everything as priority defeats the purpose.
AVIF: The Format You Should Be Using
AVIF offers 30–50% smaller files than WebP at comparable quality. Next.js supports it, but the default format order prefers WebP. Override it in your config:
// next.config.ts
const config: NextConfig = {
images: {
formats: ["image/avif", "image/webp"],
deviceSizes: [640, 750, 828, 1080, 1200],
imageSizes: [16, 32, 48, 64, 96, 128, 256],
},
};
The trade-off is encoding time — AVIF is slower to generate than WebP. For static sites with next export, this adds build time. For on-demand optimization (the default), the first request for each size/format combination will be slower, but subsequent requests are cached.
Self-Hosting Image Optimization
If you're not on Vercel, Next.js uses Sharp for image optimization. This works fine, but for high-traffic sites, consider running imgproxy as a separate service. It's purpose-built for on-the-fly image transformation, handles caching efficiently, and removes the optimization load from your Next.js process.
Blur Placeholders for Perceived Performance
Use placeholder="blur" with a base64 blur data URL for a smooth loading experience. For static imports, Next.js generates this automatically. For dynamic images, generate the blur hash at upload time or use a tiny (10px wide) thumbnail as the blur source.
Takeaways
- Use
fillmode with explicitsizesfor responsive images — don't guess dimensions - Add
priorityonly to your LCP image (hero/cover), never to all images - Enable AVIF-first format order for 30–50% savings over WebP
- Run imgproxy for self-hosted deployments under heavy traffic
- Generate blur placeholders at upload time for dynamic images
Admin
Cal.com
Open source scheduling — tự host booking system, thay thế Calendly. Free & privacy-first.
Vercel
Deploy Next.js app trong 30 giây. Free tier rộng rãi cho side projects.
Bình luận (0)
Đăng nhập để bình luận
Chưa có bình luận nào. Hãy là người đầu tiên!