懒加载的过度使用对性能的影响

以 Core Web Vitals 为中心,为图片懒加载提供数据驱动的建议。

懒加载是一种延迟下载资源的技巧,直到需要时才下载,以节省数据并减少关键资产的网络争用。它在 2019 年 成为 Web 标准,如今大多数主流浏览器都支持用于图片的 loading="lazy"

本指南总结了如何分析公开的 Web 透明度数据和临时 A/B 测试,以了解浏览器级图片懒加载的采用和性能特征。研究结果表明,懒加载可能是减少不必要的图片字节的绝佳工具,但过度使用会产生负面的性能影响。具体而言,此分析表明,更积极地加载初始视口内的图片,同时自由地懒加载其余图片,可以让我们两全其美:加载更少的字节并改进 Core Web Vitals

采用率

根据 HTTP Archive 中的最新数据,内置图片懒加载被 29% 的网站使用,并且采用率正在快速增长。

Pie chart showing WordPress making up 84.1% of lazy loading adoption, other CMSs 2.3%, and non-CMSs 13.5%.
使用浏览器级图片懒加载的网站类型细分。来源

查询 HTTP Archive 项目中的原始数据,我们可以更清楚地了解哪些类型的网站正在推动采用:84% 的使用浏览器级图片懒加载的网站使用 WordPress,2% 使用其他 CMS,其余 14% 不使用已知的 CMS。这些结果清楚地表明 WordPress 如何引领采用潮流

Timeseries chart of lazy loading adoption with WordPress being the predominant player compared to other CMSs and non-CMSs, with similar proportions to the previous chart. Total adoption is shown to have rapidly increased from 1% to 17% from July 2020 to June 2021.
使用浏览器级图片懒加载的网站类型细分。来源

采用率也值得注意。一年前的 2020 年 7 月,在约 600 万个网站的语料库中,使用懒加载的 WordPress 网站占数万个(占总数的 1%)。此后,仅 WordPress 中的懒加载采用率就已增长到超过 100 万个网站(占总数的 14%)。

相关性性能

深入挖掘 HTTP Archive,可以比较使用和不使用浏览器级图片懒加载的页面在 最大内容ful 绘制 (LCP) 指标方面的性能。Chrome 用户体验报告 (CrUX) 中的真实用户体验提供了 LCP 数据,而不是实验室中的综合测试。以下图表使用箱线图来可视化每个页面第 75 个百分位 LCP 的分布:线条代表第 10 个和第 90 个百分位,箱子代表第 25 个和第 75 个百分位。

Box and whisker chart showing the 10, 25, 75, and 90th percentiles for pages that do and do not use browser-level image lazy loading. Comparatively, the LCP distribution of pages that do not use it is faster than those that do.
所有页面的第 75 个百分位 LCP 体验分布,按是否使用浏览器级图片懒加载进行细分。来源

不使用懒加载的页面的中位数第 75 个百分位 LCP 为 2,922 毫秒,而使用懒加载的页面的中位数为 3,546 毫秒。总体而言,使用懒加载的网站往往具有较差的 LCP 性能。

重要的是要指出,这些是相关性结果,它们不一定表明懒加载是性能较慢的原因。假设,如果 WordPress 网站往往速度稍慢,并且考虑到它们在懒加载队列中所占的比例,这可以解释这种差异。为了消除这种可变性,可以将重点缩小到专门针对 WordPress 网站。

Box and whisker chart showing the 10, 25, 75, and 90th percentiles for WordPress pages that do and do not use browser-level image lazy loading. Comparatively, the LCP distribution of pages that do not use it is faster than those that do, similar to the previous chart.
WordPress 页面的第 75 个百分位 LCP 体验分布,按是否使用浏览器级图片懒加载进行细分。来源

不幸的是,当深入研究 WordPress 页面时,也出现了相同的模式;那些使用懒加载的页面往往具有较慢的 LCP 性能。不使用懒加载的 WordPress 页面的中位数第 75 个百分位 LCP 为 3,495 毫秒,而使用懒加载的页面的中位数为 3,768 毫秒。

这仍然不能证明懒加载导致页面变慢,但使用它确实与性能较慢相吻合。为了尝试回答因果关系问题,我们设置了一个基于实验室的 A/B 测试。

因果性能

A/B 测试的目标是证明或反驳以下假设:内置图片懒加载(在 WordPress 核心中实现)导致 LCP 性能降低和图片字节数减少。使用的方法是使用 twentytwentyone 主题测试演示 WordPress 网站。对存档页和单页类型(类似于主页和文章页)在桌面设备和模拟移动设备上使用 WebPageTest 进行了测试。测试了启用和禁用懒加载的页面的每种组合,并且每个测试运行了九次以获得中位数 LCP 值和图片字节数。

系列 默认 已禁用 与默认值的差异
twentytwentyone-archive-desktop 2,029 1,759 -13%
twentytwentyone-archive-mobile 1,657 1,403 -15%
twentytwentyone-single-desktop 1,655 1,726 4%
twentytwentyone-single-mobile 1,352 1,384 2%
通过禁用示例 WordPress 页面上的浏览器级图片懒加载,LCP 的变化 (毫秒)。

这些结果比较了桌面设备和移动设备上存档页和单页测试的中位数 LCP(以毫秒为单位)。当在存档页上禁用懒加载时,LCP 得到了显着改善。但是,在单页上,它几乎没有差别。

禁用懒加载似乎使单页稍微快一些。但是,桌面设备和移动设备测试的 LCP 差异都小于一个标准差,因此这可以归因于方差,并将变化视为总体中性。相比之下,存档页的差异接近两到三个标准差。

系列 默认 已禁用 与默认值的差异
twentytwentyone-archive-desktop 577 1173 103%
twentytwentyone-archive-mobile 172 378 120%
twentytwentyone-single-desktop 301 850 183%
twentytwentyone-single-mobile 114 378 233%
通过禁用示例 WordPress 页面上的浏览器级图片懒加载,图片字节数 (KB) 的变化。

这些结果比较了每个测试的图片字节数中位数(以 KB 为单位)。正如预期的那样,懒加载对于减少图片字节数具有非常明显的积极作用。如果真实用户滚动浏览整个页面,所有图片仍会在它们进入视口时加载,但这些结果显示了初始页面加载的性能改进。

为了总结 A/B 测试的结果,WordPress 使用的懒加载技术非常清楚地帮助减少了图片字节数,但代价是延迟了 LCP。

测试修复方案

对于此实验,WordPress 当前懒加载实现的最重要方面是它懒加载视口内的图片(首屏)。CMS 博客文章 承认这是一个要避免的模式,但当时的实验数据表明,对 LCP 的影响很小,并且值得简化 WordPress 核心中的实现。

鉴于这些新数据,我们创建了一个实验性修复方案,该方案避免懒加载首屏以上的图片,并在与第一个 A/B 测试相同的条件下测试了该修复方案。

系列 默认 已禁用 修复方案 与默认值的差异 与禁用的差异
twentytwentyone-archive-desktop 2,029 1,759 1,749 -14% -1%
twentytwentyone-archive-mobile 1,657 1,403 1,352 -18% -4%
twentytwentyone-single-desktop 1,655 1,726 1,676 1% -3%
twentytwentyone-single-mobile 1,352 1,384 1,342 -1% -3%
通过针对示例 WordPress 页面上的浏览器级图片懒加载提出的修复方案,LCP 的变化 (毫秒)。

这些结果更有希望。仅懒加载首屏以下的图片会导致 LCP 回归完全逆转,甚至可能比完全禁用懒加载有轻微改进。怎么可能比不使用懒加载更快呢?一种解释是,通过不加载首屏以下的图片,LCP 图片的网络争用较少,这使其能够更快地加载。

系列 默认 已禁用 修复方案 与默认值的差异 与禁用的差异
twentytwentyone-archive-desktop 577 1173 577 0% -51%
twentytwentyone-archive-mobile 172 378 172 0% -54%
twentytwentyone-single-desktop 301 850 301 0% -65%
twentytwentyone-single-mobile 114 378 114 0% -70%
通过针对示例 WordPress 页面上的浏览器级图片懒加载提出的修复方案,图片字节数 (KB) 的变化。

就图片字节数而言,与默认行为相比,该修复方案绝对没有变化。这很棒,因为这是当前方法的优势之一。

此修复方案带有一些注意事项。WordPress 在服务器端确定要懒加载哪些图片,这意味着它不知道用户的视口大小或图片是否最初在视口内加载。因此,该修复方案使用有关图片在标记中相对位置的启发式方法来猜测它是否在视口中加载。具体来说,如果图片是页面上的第一个特色图片或主要内容中的第一张图片,则假定它位于首屏上方或附近,并且不会被懒加载。

页面级条件(如标题中的字数或主要内容中早期段落文本的数量)可能会影响图片是否在视口内。还有用户级条件可能会影响启发式方法的准确性,尤其是视口大小和使用更改页面滚动位置的锚链接。

由于这些原因,重要的是要承认该修复方案仅经过校准,以在一般情况下提供良好的性能,并且可能需要进行微调以使这些结果适用于所有实际场景。

实施

既然已经确定了懒加载图片的更好方法,并且可以节省所有图片并加快 LCP 性能,网站如何开始使用它呢?最高优先级的更改是向 WordPress 核心提交补丁以实施实验性修复方案。CMS 的浏览器级懒加载 博客文章中的指南也将更新,以阐明首屏以上懒加载的负面影响以及 CMS 如何使用启发式方法来避免它。

由于这些最佳实践适用于所有 Web 开发者,因此在 Lighthouse 等工具中标记懒加载反模式也可能很有价值。如果您有兴趣关注该审计的进展情况,请参阅 GitHub 上的 功能请求。在此之前,开发者可以做的一件事是向其字段数据添加更详细的日志记录,以查找 LCP 元素被懒加载的实例。

new PerformanceObserver((list) => {
  const latestEntry = list.getEntries().at(-1);

  if (latestEntry?.element?.getAttribute('loading') == 'lazy') {
    console.warn('Warning: LCP element was lazy loaded', latestEntry);
  }
}).observe({type: 'largest-contentful-paint', buffered: true});

上面的 JavaScript 代码段将评估最新的 LCP 元素,如果它是懒加载的,则记录警告。

这也突出了懒加载技术的尖锐边缘以及平台级别 API 改进的潜力。例如,Chromium 中存在一个开放问题,实验 本机急切加载前几张图片,类似于修复方案,尽管有 loading 属性。

结论

如果您的网站使用浏览器级图片懒加载,请检查它的实现方式并运行 A/B 测试,以更好地了解其性能成本。它可能会受益于更积极地加载首屏以上的图片。如果您有一个 WordPress 网站,希望很快就会在 WordPress 核心中发布补丁。如果您正在使用其他 CMS,请确保他们意识到此处描述的潜在性能问题。

尝试相对较新的 Web 平台 API 可能会带来风险和回报——它们被称为前沿功能是有原因的。虽然我们开始感受到浏览器级图片懒加载的棘手性,但我们也看到了如何使用它来实现更好性能的优势。

图片由 Frankie LopezUnsplash 上拍摄