Next.js image optimization feature is provided through the next/image component, which is a powerful tool that automatically optimizes images to improve performance and user experience.
next/image Component Basics
Basic Usage
javascriptimport Image from 'next/image'; export default function Page() { return ( <Image src="/hero.jpg" alt="Hero image" width={800} height={600} /> ); }
Required Props
src: Image path (local or remote)width: Image width (integer)height: Image height (integer)alt: Alternative text (for accessibility)
Image Optimization Features
1. Automatic Format Conversion
Next.js automatically converts images to modern formats (WebP, AVIF) to reduce file size.
javascript<Image src="/photo.jpg" alt="Photo" width={800} height={600} // Automatically converts to WebP or AVIF />
2. Responsive Images
Automatically generates different image sizes and loads appropriate size based on device.
javascript<Image src="/responsive.jpg" alt="Responsive image" width={1200} height={800} sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw" // Generates multiple sizes: 640w, 750w, 828w, 1080w, 1200w, 1920w, 2048w, 3840w />
3. Lazy Loading
By default, images are lazy loaded and only load when they enter the viewport.
javascript<Image src="/lazy.jpg" alt="Lazy loaded image" width={800} height={600} // Lazy loading enabled by default /> // Disable lazy loading (above-the-fold images) <Image src="/hero.jpg" alt="Hero image" width={800} height={600} priority // Disables lazy loading, loads with priority />
4. Blur Placeholder
Displays a blurred placeholder before image loads, improving user experience.
javascript<Image src="/photo.jpg" alt="Photo" width={800} height={600} placeholder="blur" blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBD..." />
5. Prevent Layout Shift
By setting explicit width and height, prevents layout shift when image loads.
javascript<Image src="/photo.jpg" alt="Photo" width={800} height={600} // Reserves space, prevents layout shift />
Advanced Usage
1. Remote Images
Configure allowed remote image domains.
javascript// next.config.js module.exports = { images: { remotePatterns: [ { protocol: 'https', hostname: 'example.com', port: '', pathname: '/images/**', }, { protocol: 'https', hostname: 'cdn.example.com', }, ], }, };
Using remote images:
javascript<Image src="https://example.com/images/photo.jpg" alt="Remote image" width={800} height={600} />
2. Dynamic Images
javascriptimport Image from 'next/image'; export default function ProductGallery({ images }) { return ( <div> {images.map((image) => ( <Image key={image.id} src={image.url} alt={image.alt} width={image.width} height={image.height} placeholder="blur" blurDataURL={image.blurDataURL} /> ))} </div> ); }
3. Image Fill Mode
javascript<Image src="/photo.jpg" alt="Photo" width={800} height={600} fill // Fills parent container style={{ objectFit: 'cover' }} />
4. Image Quality Control
javascript<Image src="/photo.jpg" alt="Photo" width={800} height={600} quality={80} // Default 75, range 1-100 />
5. Custom Loader
javascriptimport Image from 'next/image'; const imageLoader = ({ src, width, quality }) => { return `https://cdn.example.com/${src}?w=${width}&q=${quality || 75}`; }; export default function Page() { return ( <Image loader={imageLoader} src="photo.jpg" alt="Photo" width={800} height={600} /> ); }
Configuration Options
next.config.js Configuration
javascript// next.config.js module.exports = { images: { // Device sizes deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840], // Image sizes imageSizes: [16, 32, 48, 64, 96, 128, 256, 384], // Image formats formats: ['image/avif', 'image/webp'], // Minimum cache TTL (seconds) minimumCacheTTL: 60, // Disable static imports disableStaticImages: false, // Disable optimization unoptimized: false, // Dangerously allow all domains (not recommended) dangerouslyAllowSVG: false, // Content security policy contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;", // Content disposition type contentDispositionType: 'attachment', // Remote image patterns remotePatterns: [ { protocol: 'https', hostname: 'example.com', port: '', pathname: '/images/**', }, ], // Domain list (deprecated, use remotePatterns) domains: ['example.com'], }, };
Real-world Use Cases
1. E-commerce Product Images
javascriptimport Image from 'next/image'; export default function ProductCard({ product }) { return ( <div className="product-card"> <Image src={product.image} alt={product.name} width={400} height={400} priority // Above-the-fold products load with priority placeholder="blur" blurDataURL={product.blurDataURL} sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw" /> <h3>{product.name}</h3> <p>${product.price}</p> </div> ); }
2. Blog Post Cover Images
javascriptimport Image from 'next/image'; export default function BlogPost({ post }) { return ( <article> <Image src={post.coverImage} alt={post.title} width={1200} height={630} priority // Blog post covers load with priority placeholder="blur" blurDataURL={post.blurDataURL} sizes="100vw" /> <h1>{post.title}</h1> <p>{post.excerpt}</p> </article> ); }
3. User Avatars
javascriptimport Image from 'next/image'; export default function UserAvatar({ user, size = 40 }) { return ( <div className="avatar"> <Image src={user.avatar || '/default-avatar.png'} alt={user.name} width={size} height={size} className="rounded-full" placeholder="blur" blurDataURL={user.blurDataURL} /> </div> ); }
4. Image Gallery
javascript'use client'; import { useState } from 'react'; import Image from 'next/image'; export default function ImageGallery({ images }) { const [selectedIndex, setSelectedIndex] = useState(0); return ( <div className="gallery"> <div className="main-image"> <Image src={images[selectedIndex].url} alt={images[selectedIndex].alt} width={1200} height={800} priority placeholder="blur" blurDataURL={images[selectedIndex].blurDataURL} /> </div> <div className="thumbnails"> {images.map((image, index) => ( <button key={image.id} onClick={() => setSelectedIndex(index)} className={index === selectedIndex ? 'active' : ''} > <Image src={image.url} alt={image.alt} width={150} height={100} placeholder="blur" blurDataURL={image.blurDataURL} /> </button> ))} </div> </div> ); }
5. Responsive Hero Image
javascriptimport Image from 'next/image'; export default function HeroSection() { return ( <section className="hero"> <Image src="/hero.jpg" alt="Hero image" width={1920} height={1080} priority placeholder="blur" blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBD..." sizes="100vw" style={{ width: '100%', height: 'auto', objectFit: 'cover', }} /> <div className="hero-content"> <h1>Welcome to Our Site</h1> <p>Discover amazing content</p> </div> </section> ); }
Performance Optimization Tips
1. Use blurDataURL
javascript// Generate blur placeholder import { getPlaiceholder } from 'plaiceholder'; export async function getBlurDataURL(src) { const buffer = await fetch(src).then(res => res.arrayBuffer()); const { base64 } = await getPlaiceholder(buffer); return base64; } // Usage const blurDataURL = await getBlurDataURL('/photo.jpg'); <Image src="/photo.jpg" alt="Photo" width={800} height={600} placeholder="blur" blurDataURL={blurDataURL} />
2. Optimize Image Sizes
javascript// Use appropriate sizes for different scenarios // Small thumbnail <Image src="/thumb.jpg" alt="Thumbnail" width={150} height={150} /> // Medium image <Image src="/medium.jpg" alt="Medium" width={400} height={300} /> // Large image <Image src="/large.jpg" alt="Large" width={1200} height={800} />
3. Use Appropriate Image Formats
javascript// next.config.js module.exports = { images: { formats: ['image/avif', 'image/webp'], }, };
4. Lazy Load Non-critical Images
javascript// Above-the-fold images use priority <Image src="/hero.jpg" alt="Hero" width={800} height={600} priority /> // Below-the-fold images use default lazy loading <Image src="/below-fold.jpg" alt="Below fold" width={800} height={600} />
5. Use CDN for Acceleration
javascript// next.config.js module.exports = { images: { remotePatterns: [ { protocol: 'https', hostname: 'cdn.example.com', }, ], }, };
Best Practices
1. Always Provide Alt Text
javascript// ✅ Good practice <Image src="/photo.jpg" alt="A beautiful sunset over the ocean" width={800} height={600} /> // ❌ Bad practice <Image src="/photo.jpg" alt="" width={800} height={600} />
2. Set Priority for Above-the-fold Images
javascript// ✅ Good practice: Above-the-fold images load with priority <Image src="/hero.jpg" alt="Hero" width={800} height={600} priority /> // ❌ Bad practice: All images set to priority <Image src="/below-fold.jpg" alt="Below fold" width={800} height={600} priority // Unnecessary priority loading />
3. Use Appropriate sizes Attribute
javascript// ✅ Good practice: Set sizes based on layout <Image src="/photo.jpg" alt="Photo" width={800} height={600} sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw" /> // ❌ Bad practice: Don't set sizes <Image src="/photo.jpg" alt="Photo" width={800} height={600} // Browser will assume image fills viewport />
4. Optimize Image Quality
javascript// ✅ Good practice: Adjust quality based on image type <Image src="/photo.jpg" alt="Photo" width={800} height={600} quality={80} // Photos use higher quality /> <Image src="/icon.png" alt="Icon" width={64} height={64} quality={90} // Icons use even higher quality /> // ❌ Bad practice: All images use same quality <Image src="/photo.jpg" alt="Photo" width={800} height={600} quality={100} // Unnecessarily high quality />
5. Use Placeholders to Improve User Experience
javascript// ✅ Good practice: Use blur placeholder <Image src="/photo.jpg" alt="Photo" width={800} height={600} placeholder="blur" blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBD..." /> // ❌ Bad practice: Don't use placeholder <Image src="/photo.jpg" alt="Photo" width={800} height={600} // Shows blank space before image loads />
Common Questions
Q: How to handle dynamic images?
A: Use dynamic imports or fetch image info from API.
javascriptimport Image from 'next/image'; export default async function DynamicImagePage() { const images = await fetch('/api/images').then(res => res.json()); return ( <div> {images.map(image => ( <Image key={image.id} src={image.url} alt={image.alt} width={image.width} height={image.height} /> ))} </div> ); }
Q: How to disable image optimization?
A: Set unoptimized: true in next.config.js.
javascriptmodule.exports = { images: { unoptimized: true, }, };
Q: How to handle SVG images?
A: SVG images require special configuration.
javascriptmodule.exports = { images: { dangerouslyAllowSVG: true, contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;", }, };
Next.js image optimization feature can significantly improve application performance and user experience. By properly using the next/image component and configuration options, you can build high-performance image display solutions.