Next.js 的图片优化功能通过 next/image 组件提供,这是一个强大的工具,可以自动优化图片以提升性能和用户体验。
next/image 组件基础
基本用法
javascriptimport Image from 'next/image'; export default function Page() { return ( <Image src="/hero.jpg" alt="Hero image" width={800} height={600} /> ); }
必需属性
src: 图片路径(本地或远程)width: 图片宽度(整数)height: 图片高度(整数)alt: 替代文本(用于可访问性)
图片优化特性
1. 自动格式转换
Next.js 自动将图片转换为现代格式(WebP、AVIF),以减少文件大小。
javascript<Image src="/photo.jpg" alt="Photo" width={800} height={600} // 自动转换为 WebP 或 AVIF />
2. 响应式图片
自动生成不同尺寸的图片,根据设备加载合适的尺寸。
javascript<Image src="/responsive.jpg" alt="Responsive image" width={1200} height={800} sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw" // 生成多个尺寸:640w, 750w, 828w, 1080w, 1200w, 1920w, 2048w, 3840w />
3. 懒加载
默认情况下,图片会懒加载,只有当它们进入视口时才会加载。
javascript<Image src="/lazy.jpg" alt="Lazy loaded image" width={800} height={600} // 默认启用懒加载 /> // 禁用懒加载(首屏图片) <Image src="/hero.jpg" alt="Hero image" width={800} height={600} priority // 禁用懒加载,优先加载 />
4. 模糊占位符
在图片加载前显示模糊的占位符,提升用户体验。
javascript<Image src="/photo.jpg" alt="Photo" width={800} height={600} placeholder="blur" blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBD..." />
5. 避免布局偏移
通过设置明确的宽高,避免图片加载时的布局偏移。
javascript<Image src="/photo.jpg" alt="Photo" width={800} height={600} // 预留空间,避免布局偏移 />
高级用法
1. 远程图片
配置允许的远程图片域名。
javascript// next.config.js module.exports = { images: { remotePatterns: [ { protocol: 'https', hostname: 'example.com', port: '', pathname: '/images/**', }, { protocol: 'https', hostname: 'cdn.example.com', }, ], }, };
使用远程图片:
javascript<Image src="https://example.com/images/photo.jpg" alt="Remote image" width={800} height={600} />
2. 动态图片
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. 图片填充模式
javascript<Image src="/photo.jpg" alt="Photo" width={800} height={600} fill // 填充父容器 style={{ objectFit: 'cover' }} />
4. 图片质量控制
javascript<Image src="/photo.jpg" alt="Photo" width={800} height={600} quality={80} // 默认 75,范围 1-100 />
5. 自定义加载器
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} /> ); }
配置选项
next.config.js 配置
javascript// next.config.js module.exports = { images: { // 设备尺寸 deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840], // 图片尺寸 imageSizes: [16, 32, 48, 64, 96, 128, 256, 384], // 图片格式 formats: ['image/avif', 'image/webp'], // 最小化缓存时间(秒) minimumCacheTTL: 60, // 禁用静态导入 disableStaticImages: false, // 禁用优化 unoptimized: false, // 危险地允许所有域名(不推荐) dangerouslyAllowSVG: false, // 内容安全策略 contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;", // 内容处置类型 contentDispositionType: 'attachment', // 远程图片模式 remotePatterns: [ { protocol: 'https', hostname: 'example.com', port: '', pathname: '/images/**', }, ], // 域名列表(已弃用,使用 remotePatterns) domains: ['example.com'], }, };
实际应用场景
1. 电商产品图片
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 // 首屏产品优先加载 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. 博客文章封面图
javascriptimport Image from 'next/image'; export default function BlogPost({ post }) { return ( <article> <Image src={post.coverImage} alt={post.title} width={1200} height={630} priority // 文章封面优先加载 placeholder="blur" blurDataURL={post.blurDataURL} sizes="100vw" /> <h1>{post.title}</h1> <p>{post.excerpt}</p> </article> ); }
3. 用户头像
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. 图片画廊
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. 响应式英雄图片
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> ); }
性能优化技巧
1. 使用 blurDataURL
javascript// 生成模糊占位符 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; } // 使用 const blurDataURL = await getBlurDataURL('/photo.jpg'); <Image src="/photo.jpg" alt="Photo" width={800} height={600} placeholder="blur" blurDataURL={blurDataURL} />
2. 优化图片尺寸
javascript// 为不同场景使用合适的尺寸 // 小缩略图 <Image src="/thumb.jpg" alt="Thumbnail" width={150} height={150} /> // 中等图片 <Image src="/medium.jpg" alt="Medium" width={400} height={300} /> // 大图 <Image src="/large.jpg" alt="Large" width={1200} height={800} />
3. 使用合适的图片格式
javascript// next.config.js module.exports = { images: { formats: ['image/avif', 'image/webp'], }, };
4. 延迟加载非关键图片
javascript// 首屏图片使用 priority <Image src="/hero.jpg" alt="Hero" width={800} height={600} priority /> // 非首屏图片使用默认懒加载 <Image src="/below-fold.jpg" alt="Below fold" width={800} height={600} />
5. 使用 CDN 加速
javascript// next.config.js module.exports = { images: { remotePatterns: [ { protocol: 'https', hostname: 'cdn.example.com', }, ], }, };
最佳实践
1. 始终提供 alt 文本
javascript// ✅ 好的做法 <Image src="/photo.jpg" alt="A beautiful sunset over the ocean" width={800} height={600} /> // ❌ 不好的做法 <Image src="/photo.jpg" alt="" width={800} height={600} />
2. 为首屏图片设置 priority
javascript// ✅ 好的做法:首屏图片优先加载 <Image src="/hero.jpg" alt="Hero" width={800} height={600} priority /> // ❌ 不好的做法:所有图片都设置 priority <Image src="/below-fold.jpg" alt="Below fold" width={800} height={600} priority // 不必要的优先加载 />
3. 使用合适的 sizes 属性
javascript// ✅ 好的做法:根据布局设置 sizes <Image src="/photo.jpg" alt="Photo" width={800} height={600} sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw" /> // ❌ 不好的做法:不设置 sizes <Image src="/photo.jpg" alt="Photo" width={800} height={600} // 浏览器会假设图片占满视口 />
4. 优化图片质量
javascript// ✅ 好的做法:根据图片类型调整质量 <Image src="/photo.jpg" alt="Photo" width={800} height={600} quality={80} // 照片使用较高质量 /> <Image src="/icon.png" alt="Icon" width={64} height={64} quality={90} // 图标使用更高质量 /> // ❌ 不好的做法:所有图片使用相同质量 <Image src="/photo.jpg" alt="Photo" width={800} height={600} quality={100} // 不必要的高质量 />
5. 使用占位符提升用户体验
javascript// ✅ 好的做法:使用模糊占位符 <Image src="/photo.jpg" alt="Photo" width={800} height={600} placeholder="blur" blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBD..." /> // ❌ 不好的做法:不使用占位符 <Image src="/photo.jpg" alt="Photo" width={800} height={600} // 图片加载前会显示空白 />
常见问题
Q: 如何处理动态图片?
A: 使用动态导入或从 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: 如何禁用图片优化?
A: 在 next.config.js 中设置 unoptimized: true。
javascriptmodule.exports = { images: { unoptimized: true, }, };
Q: 如何处理 SVG 图片?
A: SVG 图片需要特殊配置。
javascriptmodule.exports = { images: { dangerouslyAllowSVG: true, contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;", }, };
Next.js 的图片优化功能可以显著提升应用性能和用户体验。通过合理使用 next/image 组件和配置选项,可以构建出高性能的图片展示方案。