Next.js 提供两种显示图像的方式:next/image 中的 <Image> 组件和普通 HTML 的 <img> 标签。选择错误会让您损失性能或灵活性。 以下是各自的适用场景。
next/image 的功能
<Image> 组件是 <img> 的包装器,添加了:
- 自动 WebP/AVIF 转换:根据浏览器支持将 JPEG 和 PNG 转换为 WebP 或 AVIF。
- 自动 srcset 生成:使用
deviceSizes和imageSizes配置创建多个尺寸变体。 - 懒加载:折叠以下的图像仅在进入视口时加载(使用原生
loading="lazy")。 - 防止布局偏移:通过
width和height属性预留空间,防止 CLS。 - 模糊占位符:在完整图像加载时显示低质量占位符。
- 优先加载:
priority属性为 LCP 图像添加<link rel='preload'>。
next/image 的权衡
自动化带来了约束:
- 服务器端处理:图像在请求时(或首次请求后缓存)在服务器上转换。 这增加了冷启动延迟和服务器 CPU 成本。
- 必须提供尺寸:必须提供
width和height属性,或使用fill模式。对于尺寸未知的用户上传内容可能很麻烦。 - 远程域名必须加入白名单:外部图像域名需要在
next.config.js中配置。 - 静态图像的开销:预转换的 WebP 图像即使不需要也会通过优化管道。
何时使用 next/image
- 来自 CMS 或数据库的动态图像(未知尺寸、各种格式)
- 无法预处理的用户上传图像
- 想要自动 srcset 而无需手动生成文件时
- 需要用最少代码实现模糊占位符或优先加载时
何时使用普通 img 标签
- 预优化图像:构建时已转换为 WebP 或 AVIF 的图像不会从 next/image 处理中受益。
- 已知的固定尺寸:您控制来源且已正确调整大小的静态资产。
- 避免服务器端成本:转换开销很重要且可以预处理图像的高流量页面。
- 完整 HTML 控制:具有多个来源、艺术指导或自定义加载行为的复杂
<picture>元素。
性能对比
| 场景 | next/image | img 标签 |
|---|---|---|
| 首次请求(冷启动) | 慢(服务器转换) | 快(预转换) |
| 后续请求 | 快(边缘缓存) | 快(CDN/浏览器缓存) |
| 构建时间 | 快 | 慢(如果预转换) |
| 服务器 CPU | 有使用 | 无使用 |
| srcset | 自动 | 手动 |
混合方法
许多生产 Next.js 应用同时使用两者。对动态内容(博客文章图像、来自 CMS 的产品照片)使用 <Image>,对已预优化的静态资产(英雄图像、图标、插图)使用普通 <img>。
要将静态图像预转换为 WebP,请使用 Picovert 的转换器或将 Sharp 集成到构建管道中。 完整比较请参阅 next/image vs 预转换文章。
常见错误
- 缺少 sizes 属性:没有
sizes,Next.js 默认为100vw,在桌面上加载不必要的大图像。始终将sizes设置为 与实际渲染大小匹配。 - 未在 LCP 图像上设置 priority:折叠以上的英雄图像应设置
priority,避免懒加载页面上最重要的图像。 - 没有定位父元素使用 fill 模式:
fill要求父元素具有position: relative和明确的尺寸。