← 中文资源

简体中文版本

LCP 图片劣化 — 首屏主图用上了 loading=lazy

诊断对首屏主图做懒加载导致的 LCP 劣化,用现场与实验数据确认,并在积极加载首屏的同时预留布局空间。

阅读英文原文

症状

  劣化随一个属性而来,服务出的 HTML 直接可见:hero 图上挂着 loading=“lazy”。性能面板显示后果:LCP 标记在脚本与低优先级资源之后才触发——lazy 提示把图片移出了早期加载管线。模板级改动把懒加载无差别扫到所有图片(包括首屏 LCP 元素)是典型起因;CrUX 现场数据 p75 恶化确认真实用户影响,Lighthouse 实验数据确认机制与幅度。想拿现场级证据就用 PerformanceObserver 监听 largest-contentful-paint 条目。

诊断思路

  先在 Performance 面板找 LCP 元素及其相对导航开始的到达时间;再统计服务 HTML 里 lazy 属性的分布,确认主图是否被一刀切波及;最后实验与现场对照:Lighthouse 复现机制、CrUX 验证人群影响。图片缺 width/height 会给迟到加载再叠一层布局偏移,fetchpriority 未设则主图即使 eager 也与其他资源竞争。

根因

  懒加载把图片推迟到浏览器判断其接近视口,使其在加载管线中排在布局、脚本和其他资源之后。用在首屏 LCP 图片上,就推迟了页面最大的绘制——恰好是懒加载本想保护的指标。

修复与验证

  首屏与屏外区别对待:主图 eager、显式宽高、fetchpriority=“high”;CSS 背景或脚本插入的主图用 ;第二屏起再 lazy 且同样带宽高——预留 aspect-ratio 空间让迟到的加载不再推挤布局。验证时重跑 Lighthouse 并观察 CrUX:LCP 回到改动前水平、屏外图片仍然推迟、CLS 因尺寸预留保持平坦。按猜测的折叠线把所有图都 eager 会伤到慢网络——从第二屏起用真实视口测得的分界再懒加载。

代码示例

<img src="hero.jpg" loading="lazy" alt="...">
new PerformanceObserver((list) => {
  const e = list.getEntries().at(-1);
  console.log('LCP element:', e.element, e.startTime);
}).observe({ type: 'largest-contentful-paint', buffered: true });
<!-- hero: eager, high priority, dimensioned -->
<img src="hero.jpg" width="1600" height="600"
     fetchpriority="high" alt="...">

<!-- below the fold: lazy, still dimensioned -->
<img src="gallery-1.jpg" width="800" height="600"
     loading="lazy" alt="...">
<link rel="preload" as="image" href="hero.jpg"
      fetchpriority="high">