图片加载优化 懒加载、响应式与格式选择
RainLeather
6 分钟阅读
图片加载优化 懒加载、响应式与格式选择
图片通常是页面里体积最大的资源。优化不是为了"更小",而是"只在需要时才加载需要尺寸的那一份",把带宽和首屏时间都省在刀刃上。一个图文混排的列表页,图片往往占掉总传输量的八九成,所以图片优化是前端性能里投入产出比最高的一环,比纠结打包体积更立竿见影。
懒加载:进视口才请求
传统做法是监听 scroll 计算位置,但滚动事件密集触发、还要在主线程算布局,体验差且容易算错。现代用 IntersectionObserver 在元素进入视口附近时再赋值真实地址:
const io = new IntersectionObserver((entries) => {
for (const e of entries) {
if (e.isIntersecting) {
e.target.src = e.target.dataset.src;
io.unobserve(e.target);
}
}
}, { rootMargin: '200px' });
document.querySelectorAll('img[data-src]').forEach(img => io.observe(img));
rootMargin 让图片提前 200px 开始加载,避免滚到跟前才请求导致的空白。加载完成前可用占位背景或低清图过渡,减少布局跳动。边界:懒加载不要用于首屏可见图,否则反而延迟了最关键的内容;也不要对装饰性小图标用懒加载,增加复杂度却省不了多少。
响应式:一份源多种尺寸
同一张图在手机和桌面需要的分辨率不同,硬塞大图给小屏是浪费。srcset 配合 sizes 让浏览器按视口挑尺寸:
<img
srcset="a-480.jpg 480w, a-960.jpg 960w, a-1440.jpg 1440w"
sizes="(max-width: 600px) 480px, 960px"
src="a-960.jpg"
alt="">
浏览器结合 sizes 给出的展示宽度和 devicePixelRatio,自动选最合适的一张。前提是构建时真的生成了多档图,否则 srcset 只是空摆设。经验上,准备 1x、2x 两档常足够覆盖多数场景,盲目生成五六档只会让构建产物膨胀。注意 sizes 要和实际 CSS 展示宽度一致,写错会导致浏览器选了过大或过小的图。
格式选择:体积与兼容的权衡
新一代格式(如 webp、avif)在相同观感下体积显著更小,经验上较老式 jpg/png 可省下一到数个量级的字节。但旧浏览器不支持,需用 <picture> 做回退:
<picture>
<source srcset="a.avif" type="image/avif">
<source srcset="a.webp" type="image/webp">
<img src="a.jpg" alt="">
</picture>
浏览器从上到下选第一个支持的格式,最末 img 是兜底。注意:avif 压缩率高但编码耗时,适合离线预生成,不适合实时转码;webp 编解码更均衡,兼容性也更好,是大多数项目的甜点选择。png 在需要透明且无损的场景仍有价值,不能一刀切换成有损格式。
缓存配合
图片优化还要和缓存配合才能发挥最大效果。给图片设较长的 Cache-Control 并启用内容哈希命名,可以让二次访问直接命中缓存,连网络请求都省掉。CDN 边缘缓存则把图片推到离用户更近的节点,降低首字节时间。懒加载解决"何时下载",缓存解决"下载后是否还要再下载",两者正交,应当同时做,否则只优化一端收益有限。还要注意:频繁变动的图片不适合长缓存,要通过哈希或版本号让文件名随内容变,避免用户拿到旧图。
解码与占位
大图解码也会卡主线程,给 <img> 加 decoding="async" 让解码异步进行,避免阻塞交互。首屏关键图则相反,可用 fetchpriority="high" 提示优先加载,把有限带宽让给首屏,次要图用 fetchpriority="low" 延后。低清占位图(LQIP)要足够小,它本身也占请求,过大会失去意义;可以用极小的模糊缩略图配合 CSS 模糊放大过渡,体感上几乎无感。
首屏关键图的取舍
懒加载砍掉的是非首屏图,但首屏那张主图恰恰最影响 LCP,绝不能懒加载。正确做法是首屏主图用 fetchpriority="high" 抢占带宽,其余图正常或低优先级加载。预加载 <link rel="preload" as="image"> 也能让关键图尽早进入请求队列,缩短用户看到主视觉的时间。这里有个权衡:preload 会和资源争抢带宽,只预加载真正关键的 1 到 2 张,过多反而拖累整体。经验上,先用性能面板找出 LCP 元素,再针对性优化那一张,比泛泛地给所有图加策略更有效。
边界
- 懒加载不要用于首屏可见图,否则反而延迟了最关键的内容。
- CDN 若支持按请求参数实时裁剪,前端可只传尺寸参数,省去维护多档图的负担,但要把原图尺寸限制住防止被滥用拉原图。
- 装饰性图片(图标、分割线)优先用 SVG 或 CSS 实现,比位图更轻且可缩放清晰,还能随主题变色。
- 监控真实用户的图片加载耗时,比实验室跑分更能反映分布;某些地区网络差,懒加载阈值和格式策略要因地制宜。
经验上,图片优化是"分层"的:先上懒加载拦住非首屏,再用响应式砍掉多余像素,随后用新格式压缩字节。三层叠加,首屏图片体积通常能降一大半。
浏览 0
点赞 0
评论 0