目标
一张 60 图的画廊页在访客看到任何东西之前先送出 9MB,而其中 58 张都在首屏之下。原生 loading=lazy 加一张显式高优先级的 LCP 图,能在不引入任何懒加载框架的情况下把初始负载砍掉一个数量级。关键是分清“必须立刻到”与“可以等滚动”两类资源,并守住各自的边界。
步骤要点
- 解析构建产物统计 img 标签数、带 lazy 与 fetchpriority 属性的数量,量化“全部急加载”的差距。
- 改模板:LCP 主图显式豁免懒加载并加 fetchpriority=“high”,首屏下方图片统一 loading=“lazy” 与 decoding=“async”,三方 iframe 改 data-src 加 IntersectionObserver 预载 200px。
- 重新构建后在 DevTools 用 Fast 3G 节流重载,观察首次绘制的请求数与传输量大幅回落。
- 用脚本给产物加守卫:lazy 属性数量低于阈值就构建失败,防止未来模板改动悄悄退化。
- 记录动机指标的前后值(首字节到 LCP、初始传输量),把审计到验证的闭环写进变更说明。
排错提示
加了懒加载 LCP 反而变慢,是“一刀切”规则把主图也标记了 lazy,用 fetchpriority=“high” 显式豁免,最该快的图绝不能懒;滚动时图片蹦出造成卡顿,是没预留空间引发回流,补 width/height 或 aspect-ratio,并给观察器加 rootMargin 提前加载;三方 iframe 无视 loading 属性时它走 script 自装,改用点击激活的门面或首次交互后再加载。
适用边界
原生懒加载依赖浏览器启发式,要在受众真实使用的低端设备上验证行为;推迟挂件是拿即时可用性换速度,点击激活改变了用户体验,该由产品决策而不只是工程决策。
代码示例
<!-- before: 60 eager <img>, 9MB, LCP 4.1s on Fast 3G -->
<!-- after -->
<img src="/hero.webp" width="1600" height="900"
fetchpriority="high" decoding="async" alt="..."> <!-- the ONE eager -->
<img src="/piece-01.webp" width="640" height="640"
loading="lazy" decoding="async" alt="..."> <!-- 58 of these -->
<!-- metrics: initial transfer 9.0MB -> 1.3MB -->
<!-- LCP 4.1s -> 1.8s, CLS unchanged 0.02 -->