图片压缩与优化
面试速答(30 秒版 TL;DR)
图片优化不要只回答“转 WebP、压缩一下”,更完整的表达应该是:
- 先控制源图:上传前就不要给前端一张远超展示尺寸的大图。
- 再选格式:照片优先有损压缩格式,图标和透明素材优先无损或矢量格式。
- 按场景下发:同一张图给不同设备、不同屏幕密度、不同容器尺寸,应该返回不同版本。
- 再谈加载策略:首屏关键图优先,非首屏图懒加载,避免图片挤占关键带宽。
- 最后做稳定性优化:预留尺寸、防止 CLS、做好缓存和降级。
一句话总结:
图片优化的本质,不是把所有图片都压到最小,而是在“画质、体积、解码成本、加载时机、视觉稳定性”之间做场景化取舍。
为什么图片经常是性能大头?
图片是前端页面里最常见、也最容易失控的资源类型,因为它同时影响:
- 网络传输体积
- 解码和光栅化开销
- 首屏 LCP
- 页面稳定性 CLS
很多页面慢,不是 JS 太大,而是:
- Hero 图原图几 MB
- 列表页缩略图尺寸远大于展示尺寸
- 移动端还在下发桌面大图
- 懒加载做了,但尺寸没预留,页面跳动明显
所以图片优化通常要按链路回答,而不是只盯着“压缩率”。
先记优化链路,不要把“压缩”和“加载策略”混成一个点。
一、先做对一件事:不要把“源图问题”甩给浏览器
这是最常被忽略、但收益最大的部分。
1. 展示多大,就尽量提供多大的资源
如果页面上实际只显示 300 x 200 的卡片图,却下发 4000 x 3000 的原图,即使浏览器最后缩小显示,也已经付出了:
- 下载成本
- 解码成本
- 内存占用
所以图片优化的第一原则不是“前端压缩”,而是“源图不要离谱”。
2. 一张图不应该只准备一个版本
真实页面中,同一资源通常会在不同场景下展示:
- 列表缩略图
- 详情页大图
- 移动端窄屏
- 高清屏 2x / 3x
如果所有场景共用同一张大图,通常不是最优方案。更合理的做法是让图片服务或构建流程生成多套尺寸。
二、格式怎么选:不要背结论,要知道为什么
1. JPEG / JPG
适合:
- 照片
- 色彩丰富的实拍图
- 对极致清晰边缘要求不高的内容
特点:
- 有损压缩
- 压缩率通常不错
- 不支持透明
2. PNG
适合:
- 透明背景图片
- 线条清晰、颜色块明显的图
- 对无损保真更敏感的素材
特点:
- 体积通常比照片类 JPEG 更大
- 支持透明
- 不适合拿来存大量照片素材
3. WebP
适合:
- 大多数 Web 页面通用场景
- 既想要较好压缩率,又希望兼顾透明能力
特点:
- 既支持有损,也支持无损
- 在很多图片场景下比 JPEG / PNG 更省体积
- 常作为 Web 端默认优先格式
4. AVIF
适合:
- 对极致体积敏感的图片密集型页面
- 能接受更复杂编码链路的项目
特点:
- 压缩效率通常更高
- 但编码更慢,某些场景的解码和兼容策略也要评估
5. SVG
适合:
- 图标
- Logo
- 简单插画
- 几何图形
特点:
- 本质是矢量描述
- 缩放不失真
- 不适合复杂照片内容
面试里更像工程师的说法是:
图片格式没有绝对最优,只有场景最优。照片看压缩率和感知画质,透明素材看透明支持和清晰边缘,图标优先矢量。
三、压缩不是越狠越好,关键是“感知质量”
图片压缩常见有两个方向:
| 方向 | 含义 | 适用场景 |
|---|---|---|
| 有损压缩 | 牺牲部分细节换体积 | 照片、背景图、内容图 |
| 无损压缩 | 尽量不损失像素信息 | 图标、界面元素、对边缘敏感的素材 |
1. 该怎么理解“压缩质量”?
不是把图片体积压到最小,而是让用户在正常观看距离下:
- 看不出明显劣化
- 不出现明显噪点、色块、边缘糊掉
- 但体积显著下降
这也是为什么线上常常不会保留摄影原图级质量,而是使用“足够清晰”的版本。
2. 为什么有时候体积小了,页面反而不一定更快?
因为图片性能不只看传输,还要看:
- 解码成本
- 渲染成本
- 是否阻塞关键资源
例如一张首屏大图虽然压得很小,但如果没有优先加载,它仍然可能拖慢 LCP;反过来,一张图即使体积不算夸张,但如果尺寸没预留,也会带来 CLS。
四、响应式图片:同一张图,应该按设备能力下发
响应式图片的目标不是“炫技”,而是让浏览器自己选更合适的版本。
最常见的是 srcset + sizes:
<img
src="/images/card-640.webp"
srcset="/images/card-320.webp 320w, /images/card-640.webp 640w, /images/card-960.webp 960w"
sizes="(max-width: 768px) 100vw, 320px"
width="320"
height="180"
alt="课程封面"
/>
这段配置表达的是:
- 小屏设备不必下大图
- 大屏或高像素密度设备可以拿更高分辨率资源
- 同时通过
width、height预留布局空间
如果还要做格式协商,可以结合 picture:
<picture>
<source type="image/avif" srcset="/images/banner-768.avif 768w, /images/banner-1280.avif 1280w" sizes="100vw" />
<source type="image/webp" srcset="/images/banner-768.webp 768w, /images/banner-1280.webp 1280w" sizes="100vw" />
<img src="/images/banner-1280.jpg" width="1280" height="720" alt="活动横幅" />
</picture>
五、加载策略:谁该先到,谁该后到
1. 首屏关键图优先
对首页横幅、文章头图、商品主图这类会直接影响 LCP 的图片,关键不是“懒加载”,而是尽早拿到。
常见策略:
- 让首屏关键图尽量出现在 HTML 早期
- 避免依赖过深的 JS 才生成图片节点
- 对真正关键的图片使用更高优先级加载策略
2. 非首屏图片懒加载
列表流、推荐区、评论区、瀑布流中的图片,通常更适合懒加载。
<img src="/images/product-480.webp" loading="lazy" width="240" height="240" alt="商品图片" />
懒加载的收益在于:
- 减少首屏带宽竞争
- 降低首屏解析后的图片请求数
- 节省用户根本不会看到的资源下载
但要注意:
- 首屏第一屏内的 LCP 图片通常不适合盲目
loading="lazy" - 图片未预留尺寸时,即使懒加载成功,也可能造成布局抖动
六、CLS 视角:图片优化不只是“更小”,还要“更稳”
很多页面首屏分数差,不是因为图片太慢,而是图片一出来就把布局顶开了。
最直接的做法是预留尺寸:
<img src="/images/avatar.webp" width="96" height="96" alt="用户头像" />
或者给容器固定宽高比:
.cover {
aspect-ratio: 16 / 9;
overflow: hidden;
}
.cover img {
width: 100%;
height: 100%;
object-fit: cover;
}
面试里可以直接说:
图片优化除了看 KB,还要看是否引起 CLS。体积小但布局乱跳,用户感知一样差。
七、工程里常见的图片优化流水线
真实项目通常不会依赖开发者手工处理每一张图片,而是把流程做成自动化。
这一套比“前端页面里临时写个压缩逻辑”更稳定,因为它能统一控制:
- 尺寸规则
- 格式策略
- 压缩质量
- 缓存命名
典型题 & 标准答法
Q1:图片优化有哪些常见手段?
我会按链路回答:先控制源图尺寸,再选合适格式,再做压缩,再生成多尺寸版本,然后按设备和布局下发,最后结合首屏优先、懒加载、尺寸预留和 CDN 缓存做整体优化。
Q2:为什么只把图片转成 WebP 还不够?
因为图片问题不只有格式。即使格式更先进,如果源图尺寸过大、首屏加载时机不对、没有响应式下发、没有预留尺寸,页面仍然可能慢或者抖。
Q3:如何避免图片导致 CLS?
给图片写明确的 width、height,或给容器设置稳定的宽高比,让浏览器在图片真正下载完成前就能预留布局空间。
Q4:懒加载是不是所有图片都该开?
不是。首屏关键图如果也懒加载,可能会拖慢 LCP。懒加载更适合首屏外图片。
常见误区
-
误区 1:图片优化等于转 WebP。 格式只是其中一步,源图尺寸和加载策略往往更关键。
-
误区 2:只看文件体积,不看解码和渲染。 图片性能是“下载 + 解码 + 显示”的总和。
-
误区 3:所有图都懒加载。 这会伤到真正影响首屏体验的关键图片。
-
误区 4:缩略图直接用原图缩放显示。 浏览器只是显示变小,下载和解码成本并没有同步变小。
速记要点
- 图片优化先看源图尺寸,再看格式和压缩。
- 同一张图要按设备和布局生成多版本,而不是全端共用一张大图。
- 首屏关键图优先,非首屏图懒加载。
- 预留尺寸、防止 CLS,是图片优化里经常被忽略但很重要的一环。