乐闻世界logo
搜索文章和话题

Next.js 的图片优化是如何工作的?

2月17日 23:30

Next.js 的图片优化功能通过 next/image 组件提供,这是一个强大的工具,可以自动优化图片以提升性能和用户体验。

next/image 组件基础

基本用法

javascript
import 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. 动态图片

javascript
import 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. 自定义加载器

javascript
import 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. 电商产品图片

javascript
import 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. 博客文章封面图

javascript
import 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. 用户头像

javascript
import 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. 响应式英雄图片

javascript
import 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 获取图片信息。

javascript
import 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

javascript
module.exports = { images: { unoptimized: true, }, };

Q: 如何处理 SVG 图片?

A: SVG 图片需要特殊配置。

javascript
module.exports = { images: { dangerouslyAllowSVG: true, contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;", }, };

Next.js 的图片优化功能可以显著提升应用性能和用户体验。通过合理使用 next/image 组件和配置选项,可以构建出高性能的图片展示方案。

标签:Next.js