我盯了三年 LCP 分数,今天才发现图片一直白屏——根子不在格式,在加载顺序
我盯了三年 LCP 分数,今天才发现图片一直白屏——根子不在格式,在加载顺序。
LCP 是 Core Web Vitals 里最能反映用户感知的一个指标。页面最「大」的元素渲染出来的那一刻,就是 LCP 时间。但很多人 LCP 分数提不上去,不是因为图片太大,而是因为加载顺序错了。
两张图,同样的体积,不一样的 LCP。
你可能觉得只要上了 WebP、加了懒加载、优化了 CDN,LCP 就搞定了。但懒加载恰恰是 LCP 的大敌——你让 LCP 元素延迟加载,分数怎么可能好看?
真正影响 LCP 的,是三件事:加载时机、资源优先级、渲染阻塞。
LCP 图片必须 eager + fetchpriority=high + decoding=async。loading=eager 是默认值,但你用了懒加载插件,很容易把 LCP 图片也懒掉了。LCP 元素必须 eager。
fetchpriority=high 告诉浏览器:这个资源的优先级高于其他图片。浏览器在预扫描 HTML 时会根据这个属性调整请求顺序。没有这个,高分辨率 LCP 图片可能排在后面,等前面的资源让路。
decoding=async 让图片解码异步进行,不阻塞主线程。实测在低端设备上,这个属性可以让 LCP 再快 50-100ms。
Preload 也很关键,但很多人用错了。
正确:直接 preload LCP 图片本身 <link rel=preload as=image href=/hero.webp fetchpriority=high>
错误:preload 背景图,浏览器当 CSS 资源处理。
Preload LCP 图片时,as=image 必须加上,而且要带上 fetchpriority=high。否则浏览器会把它当成普通图片,不会提升优先级。
另外,如果你用 CSS 的背景图作为 LCP 元素(很常见的场景),preload 就没法用了——<link rel=preload> 不支持 as=css-background。这种场景下,用 JavaScript 提前创建 Image 对象预加载更有效。
现代格式只是基础,不是答案。
WebP 和 AVIF 确实比 JPEG 小 30-50%,但这是优化链路的最后一环。如果图片加载顺序错了、优先级没设对、还在懒加载,用了 AVIF 也没用。
一个实测数据:同样一张 200KB 的 LCP 图片,懒加载时 LCP 是 3.8s,eager 加载是 1.2s;加上 fetchpriority=high 后是 0.9s;再加上 preload 是 0.7s。这三个组合才是 LCP 优化的完整链路。
落到实际,给你一个检查清单:
第一步,打开 Chrome DevTools 的 Network 面板,过滤 Img,看 LCP 图片的加载时机。是不是被懒加载插件拦截了?
第二步,看 LCP 图片的优先级。在 Network 面板的 Priority 列,高优先级应该是 High,不是 Low。
第三步,检查 LCP 元素是 <img> 还是 CSS 背景图。如果是背景图,用 JavaScript Image 对象预加载比 preload 更可靠。
第四步,把图片格式换成 AVIF,配合 eager + fetchpriority,这才是完整优化。
下一步:去 Lighthouse 跑一个你的真实页面,找到 LCP 时间,然后按上面四条逐条检查。你会发现,LCP 优化大多数时候不是技术问题,是顺序问题。
评论区
登录后可评论。