图片优化
本教程共 42 篇 · 第 17 篇 · 更新于 2026-07-30 · 约 8 分钟阅读
17. 图片优化
本节目标:掌握 next/image 组件的核心功能,学会自动优化图片、防止布局偏移、实现懒加载和响应式图片,让页面加载更快、体验更流畅。
为什么需要图片优化?
图片通常是网页中最大的资源。未经优化的图片会导致:
- 加载缓慢,用户等待时间长
- 图片加载时页面跳动(布局偏移)
- 浪费带宽流量
- 移动端加载大图浪费资源
Next.js 的 <Image> 组件就是为了解决这些问题而生的。它基于原生 <img> 标签扩展,提供了自动优化能力。
核心能力
<Image> 组件提供了四个关键优化:
- 尺寸优化:自动为每个设备提供合适尺寸的图片,使用 WebP 等现代格式
- 视觉稳定:自动防止图片加载时的布局偏移(CLS)
- 更快加载:原生懒加载,图片进入视口才开始加载
- 资源灵活:支持按需缩放,包括远程服务器上的图片
本地图片
使用本地图片最简单。把图片放在 public 目录或组件同级目录,然后静态引入:
// app/page.tsx
import Image from 'next/image'
import profile from './profile.png'
export default function Page() {
return (
<Image
src={profile}
alt="作者头像"
// width 和 height 会自动提供
// blurDataURL 也会自动生成
placeholder="blur" // 加载时显示模糊预览
/>
)
}
Tip静态引入图片时,Next.js 会自动获取图片的宽高和生成模糊占位图。你不需要手动指定这些属性。
如果你不想用静态引入,也可以直接指定路径:
import Image from 'next/image'
export default function Page() {
return (
<Image
src="/profile.png"
alt="作者头像"
width={500}
height={500}
/>
)
}
这种方式需要手动指定 width 和 height。
远程图片
使用远程图片时,必须手动指定宽高,因为 Next.js 在构建时无法获取远程文件信息:
import Image from 'next/image'
export default function Page() {
return (
<Image
src="https://s3.amazonaws.com/my-bucket/profile.png"
alt="作者头像"
width={500}
height={500}
/>
)
}
配置远程图片域名
出于安全考虑,Next.js 默认不允许优化任意远程图片。你需要在 next.config.ts 中配置允许的域名:
// next.config.ts
import type { NextConfig } from 'next'
const config: NextConfig = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 's3.amazonaws.com',
pathname: '/my-bucket/**',
},
],
},
}
export default config
NoteNext.js 16 写法:
remotePatterns支持通配符*(匹配单个路径段)和**(匹配任意数量的路径段)。尽量配置得具体一些,避免安全风险。
fill 模式
当你不知道图片的精确尺寸,或者想让图片自适应容器大小时,可以使用 fill 属性:
export default function Hero() {
return (
<div style={{ position: 'relative', width: '100%', height: '400px' }}>
<Image
src="/hero.jpg"
alt="首页大图"
fill
style={{ objectFit: 'cover' }}
/>
</div>
)
}
使用 fill 时要注意:
- 父元素必须有
position: relative(或fixed、absolute) - 图片默认使用
position: absolute - 可以用
objectFit控制裁剪方式:cover(裁剪填充)或contain(完整显示)
响应式图片
通过 sizes 属性,你可以告诉浏览器图片在不同屏幕宽度下的显示尺寸。这让 Next.js 生成完整的 srcset,浏览器会自动选择最合适的图片:
import Image from 'next/image'
export default function ResponsiveImage() {
return (
<div>
<Image
src="/example.png"
alt="响应式图片示例"
fill
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
style={{ objectFit: 'cover' }}
/>
</div>
)
}
sizes 的含义:
- 屏幕宽度 ≤ 768px 时,图片占满整个视口宽度
- 屏幕宽度 ≤ 1200px 时,图片占视口宽度的 50%
- 更大屏幕时,图片占视口宽度的 33%
Tip如果不设置
sizes,浏览器会默认图片占满整个视口(100vw),可能导致加载过大的图片。使用fill或响应式 CSS 时,务必设置sizes。
占位符效果
图片加载时,<Image> 支持两种占位符:
模糊占位符
静态引入的图片会自动生成模糊占位图:
<Image
src={profile}
alt="头像"
placeholder="blur"
// blurDataURL 自动生成
/>
对于远程图片,你需要手动提供 blurDataURL:
<Image
src="https://example.com/image.jpg"
alt="远程图片"
width={500}
height={500}
placeholder="blur"
blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRg..."
/>
自定义占位符
你也可以使用自定义的 Data URL 作为占位符,比如一个简单的色块或加载动画:
<Image
src="/image.png"
alt="图片"
width={500}
height={500}
placeholder="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='100%25' height='100%25' fill='%23f0f0f0'/%3E%3C/svg%3E"
/>
图片质量与格式
质量设置
quality 属性控制图片压缩质量,范围 1-100,默认 75:
<Image
src="/photo.jpg"
alt="照片"
width={800}
height={600}
quality={85}
/>
Note如果原图质量已经很低,提高 quality 值只会增加文件大小,不会改善视觉效果。
格式选择
Next.js 默认使用 WebP 格式。你可以在 next.config.ts 中配置支持的格式:
// next.config.ts
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
images: {
formats: ['image/avif', 'image/webp'],
},
}
export default nextConfig
AVIF 比 WebP 压缩率更高(约小 20%),但编码时间更长。浏览器会通过 Accept 请求头自动选择支持的格式。
预加载首屏图片
对于首屏大图(LCP 元素),可以使用 preload 属性提前加载:
<Image
src="/hero.jpg"
alt="首屏大图"
width={1200}
height={600}
preload={true}
/>
NoteNext.js 16 写法:
priority属性已被弃用,改用preload。旧版写法是priority={true}。官方建议在大多数情况下使用loading="eager"或fetchPriority="high"代替preload。
高级配置
自定义 Loader
如果你想用第三方图片优化服务(比如 Cloudinary、Imgix),可以配置自定义 loader:
'use client'
import Image from 'next/image'
const imageLoader = ({ src, width, quality }) => {
return `https://res.cloudinary.com/demo/image/upload/w_${width},q_${quality || 75}/${src}`
}
export default function Page() {
return (
<Image
loader={imageLoader}
src="sample.jpg"
alt="示例图片"
width={500}
height={500}
/>
)
}
也可以在 next.config.ts 中全局配置:
// next.config.ts
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
images: {
loader: 'custom',
loaderFile: './lib/image-loader.js',
},
}
export default nextConfig
缓存配置
优化后的图片默认缓存 4 小时。你可以调整缓存时间:
// next.config.ts
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
images: {
minimumCacheTTL: 2678400, // 31 天
},
}
export default nextConfig
设备尺寸
默认情况下,Next.js 生成 8 种不同宽度的图片。你可以自定义:
// next.config.ts
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
images: {
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
imageSizes: [32, 48, 64, 96, 128, 256, 384],
},
}
export default nextConfig
常见问题
Q: SVG 图片需要优化吗?
不需要。SVG 是矢量格式,可以无损缩放。Next.js 会自动跳过 SVG 的优化。如果你确实想用 <Image> 加载 SVG,建议加上 unoptimized:
<Image src="/logo.svg" alt="Logo" width={200} height={50} unoptimized />
Q: 静态导出能用图片优化吗?
静态导出(output: 'export')不支持运行时的图片优化。你需要配置自定义 loader,或者使用外部图片优化服务。
Q: 如何生成深色模式下的不同图片?
可以用 CSS 媒体查询切换显示不同的 <Image> 组件:
import styles from './theme-image.module.css'
import Image from 'next/image'
export default function ThemeImage({ srcLight, srcDark, alt }) {
return (
<>
<Image src={srcLight} alt={alt} className={styles.imgLight} />
<Image src={srcDark} alt={alt} className={styles.imgDark} />
</>
)
}