我上周接了个活,给一个卖手工皮具的淘宝店做详情页。老板甩过来一堆产品图,每张都是相机直出,4000x3000,单张8.7MB。我心想这有啥难的,TinyPNG一拖,完事。结果上传后网页加载了12秒,老板在群里@我:“你是想让我客户看幻灯片吗?” 要求所有图片压到200KB以内。我试了TinyPNG,嗯,8.7MB变成了1.2MB,离200KB还差6倍。又试了压图大师、iLoveIMG,最好的一张1.1MB。我当时就纳闷了,这些工具吹得天花乱坠,怎么连个200KB都搞不定?
后来我翻了一篇英文博客,才反应过来——我他妈一直在犯一个低级错误。TinyPNG这类工具只做一件事:有损压缩,也就是调整JPEG的质量参数。但它不会改变图片的分辨率。一张4000x3000的图,在网页上实际显示区域可能只有800x600,甚至更小。那多出来的几千万像素,全是废的。你质量压得再狠,像素数量摆在那儿,文件大小降不下来。这就好比你有一大桶水,只倒掉上面一层,桶还是那么重。真正的做法是:先换个小桶,再倒掉一点。
我做了个对比实验。同一张皮具特写,原图8.7MB,4000x3000。用TinyPNG压缩:1.2MB,尺寸不变。用Squoosh(Google出的那个网页工具):先resize到1600宽,再quality 75,输出186KB。用ImageMagick命令行:magick input.jpg -resize 1600x -quality 75 output.jpg,得到154KB。用Photoshop 2023的“导出为”:同样参数,172KB。你看,光是先缩放这一步,就把文件大小干掉了98%。而且1600宽在视网膜屏上配合srcset也够用。那些在线工具之所以不帮你缩放,是因为它们怕改变图片尺寸被用户骂。但你自己得明白,显示尺寸才是第一道关。
再聊聊格式。很多人还在死磕JPEG,其实WebP在同等质量下能再小30%左右。上面那张154KB的JPEG,转成WebP,cwebp -q 75 -resize 1600 0 input.jpg -o output.webp,直接变成98KB。不过WebP有个坑:iOS 14之前的Safari不支持,老安卓也不支持。所以你得用<picture>标签做降级。我一开始偷懒直接用了WebP,结果老板用他老婆的iPhone 6s打开,图片全裂。被骂了第二次。后来加了<source type="image/webp">和<img src="fallback.jpg">,才消停。
最后说个反直觉的:压得太狠反而更丑。我有一张棕色皮包的图,质量压到50,颜色过渡出现了明显的色带,像梯田一样。设计师看了直接摔鼠标:“你这图是拿座机拍的吗?” 后来我把质量调到75,色带消失,文件大小只多了20KB。所以别贪那几十KB,人眼对色带和模糊的容忍度很低。我的建议是:先定显示尺寸,再选格式,最后从质量80开始往下试,直到你眼睛觉得“有点糊了”,然后退回去10个点。
总结一下我的步骤,你照着做就行:
- 打开Chrome开发者工具,检查图片在页面上的实际渲染宽度。比如容器宽800px,那图片最大做1600px宽就够了(2倍图)。
- 用Squoosh或ImageMagick批量resize。命令行:
for f in *.jpg; do magick "$f" -resize 1600x -quality 75 "small_$f"; done。 - 转WebP。
cwebp -q 75 small_$f -o "${f%.jpg}.webp"。 - 如果不想写代码,用Squoosh网页版,手动拖几次,但批量就累了。
- 加
<picture>标签,WebP优先,JPEG兜底。 - 最后用Chrome的Lighthouse测一下,看LCP有没有改善。我那个页面从12秒降到了1.8秒。
别迷信工具,先搞懂你的图片到底要显示多大。大部分教程上来就讲算法,什么离散余弦变换,其实对普通人没用。你又不是要写编解码器。记住:像素冗余才是最大的浪费,压缩算法只是锦上添花。