关键性能问题

就目前而言,就总传输大小和每页的请求数量而言,图片是网络上最大的资产。截至 2022 年 6 月,网页的总传输大小中位数约为 2MB,其中仅图片便占了几乎一半。毫不夸张地说,优化图片请求可能是您可以进行的最大性能优化措施。

稍后,您将了解自适应图片是如何发展的,以帮助解决因“尝试为所有事件提供同一张图片”而造成的问题。 在本部分中,您将了解与图片相关的关键性能指标,以及如何改进这些指标。

延迟图片请求

虽然您将学习多种方法来确保您的图片请求尽可能小且高效,但最快的图片请求始终是永远不会发出的。因此,我想首先介绍一下,对您向用户分发图片素材资源的方式而言,哪些更改可能最具影响力:loading="lazy" 属性。

<img src="image.jpg" loading="lazy" alt="…">

此属性可确保在图片接近用户视口之前不会发出图片请求,此类请求会延迟初始网页加载(即浏览器处于最繁忙状态时)的时间,并从关键渲染路径中移除这些请求。

使用此属性在实践中可能很简单,但会对性能产生巨大的积极影响:绝不会请求始终位于用户视口内的图片,并且不会将带宽浪费在用户永远看不到的图片上。

但有一个问题:延迟这些请求意味着没有利用浏览器的超优化流程尽早请求图片。如果对靠近布局顶部的 img 元素使用 loading="lazy",因而在首次加载网页时更有可能位于用户视口中,那么最终用户会感觉这些图片的速度明显变慢。

提取优先级

loading 属性就是一个更大规模的网络标准的示例,它让开发者能够更好地控制网络浏览器确定请求优先级的方式。

您可能了解浏览器获取优先级的基本方法:例如,如果请求在文档的 <head> 中请求外部 CSS 文件,就足以阻止呈现,而请求刚好高于 </body> 的外部 JavaScript 文件的请求则会被推迟,直到呈现完成为止。如果 <img>loading 属性的值为“lazy”,则关联的图片请求将被推迟,直到浏览器确定向用户显示它为止。否则,该图片的优先级将与页面上的任何其他图片相同。

fetchpriority 属性旨在让开发者更精细地控制资源的优先级,让您能够将资源标记为相对于同一类型的资源“高”和“低”优先级。fetchpriority 的用例与 loading 属性类似,但要广泛得多。例如,您可以对仅在用户互动后显示的图片(无论该图片是否位于用户视口内)使用 fetchpriority="low",以优先显示页面上其他位置的可见图片;或者,使用 fetchpriority="high" 优先显示您认为在网页呈现后立即在视口中立即可见的图片。

请注意,fetchpriorityloading 的不同之处在于,它不会从根本上改变浏览器行为。它不会指示浏览器先于其他资源加载某些资源,而是为浏览器针对请求资源所作的决策提供重要的上下文。

衡量图片的影响

优化图片资源时,与仅总传输大小相比,感知的性能通常更重要,也更难以衡量。

网页指标可提供可衡量且富有实用价值的指标和指导,用于改善用户的 Web 体验,从而突出显示 Web 服务器响应速度缓慢、呈现问题和互动延迟等问题。核心网页指标是这些目标的一部分,主要关注用户对单个网页的直接体验,这是一组技术衡量指标,共同决定了体验带给用户的愉悦感

累积布局偏移

Cumulative Layout Shift (CLS) 是衡量视觉稳定性的一种衡量方式。它是一个指标,用于捕获随着素材资源的加载和网页呈现,网页上的内容布局发生了多大程度的偏移。由于延迟的网页字体或图片来源突然呈现,或者互动元素突然从指针移开,因此任何花费大量时间使用网页的用户在长篇文字中都失去了位置。高 CLS 最多会带来麻烦,最坏的情况下是会导致用户出错 - 例如,“取消”按钮会像用户点击一样转到以前由“确认”按钮占用的空间。

由于加载时间较长以及它们在布局中可占用的空间量很大,因此图片是导致 CLS 得分较高的常见原因。

由于现代浏览器最近进行了一些更改,因此要避免因图片问题而获得较高的 CLS 分数,比您想象的要容易。

如果您从事前端方面的工作已有几年了,那么您应该会熟悉 <img> 中的 widthheight 属性:在 CSS 被广泛采用之前,这些是控制图片大小的唯一方式。

<img src="image.jpg" height="200" width="400" alt="…">

我们不再使用这些属性,因为我们将样式设置问题与标记区分开来,尤其是在自适应网页设计有必要通过 CSS 指定基于百分比的尺寸时。在自适应设计早期,“移除未使用的 widthheight 属性”是常见建议,因为我们在 CSS 中指定的值(max-width: 100%height: auto)会覆盖它们。

<img src="image.jpg" alt="…">
img {
  max-width: 100%;
  height: auto;
}

移除上例中的 heightwidth 属性后,在这种情况下,浏览器用于确定图片高度的唯一方法是:请求来源,解析图片,然后根据应用样式表后在布局中占据的空间宽度,以其固有宽高比进行渲染。这个过程大部分发生在页面渲染之后,新计算的高度会导致布局偏移。

从 2019 年开始,我们更新了浏览器行为,以不同方式处理 widthheight 属性。而不是使用这些属性的值来确定布局中 img 元素的固定(基于像素)尺寸,而可以将这些属性视为表示图片的宽高比,但语法相同。现代浏览器会互相划分这些值,以便在呈现网页之前确定 img 元素的固有宽高比,从而在呈现布局时预留图片会占用的空间。

通常,您应始终对 <img> 使用 heightwidth 属性,并使值与图片来源的固有尺寸匹配,前提是确保您指定了 height: automax-width: 100% 以替换 HTML 属性中的高度。

<img src="image.jpg" height="200" width="400" alt="…">
img {
  max-width: 100%;
  height: auto;
}

通过在 <img> 元素中使用 widthheight 属性,您可以避免因图片问题而导致 CLS 得分过高。

请务必注意,这种方法没有缺点,因为它依赖于长久以来的浏览器行为 - 任何支持基本 CSS 的浏览器都会一如既往地工作,标记中的 heightwidth 属性会被您的样式覆盖。

虽然 widthheight 属性通过为图片预留必要的布局空间来巧妙避免 CLS 问题,但在用户等待图片传输和渲染时向其呈现空白间隙或低质量占位符也不理想。虽然您可以采取一些措施来减轻加载缓慢的图片的可衡量和可感知的影响,但要想更快地将完全渲染的图片呈现给用户,唯一的方法是缩减其传输大小。

最大内容渲染时间

Largest Contentful Paint (LCP) 用于衡量渲染用户视口中可见的最大“内容”元素(在可见页面中占据最大比例的内容元素)所需的时间。这在界面上看起来可能过于具体,但从用户的角度来看,该元素实际代表网页的大部分内容已呈现的位置。LCP 是衡量(感知)性能的重要指标。

DOMContentLoadedwindow.onload 事件等指标有助于确定从技术上讲,加载当前页面的过程何时完成,但它们不一定对应于用户的页面体验。在用户视口之外渲染元素时出现的轻微延迟会被纳入这两个指标的考量范围内,但真实用户很可能完全无法检测到。LCP 较长意味着网页对用户的第一印象(当前视口内最重要的内容)是网页运行缓慢或完全损坏。

LCP 捕获的用户感知会直接影响用户体验。Vodafone 去年刚刚完成的一项实验发现,LCP 提升 31% 不仅让销量提高了 8%,其结果本身就是这一令人满意的成果;此外,该公司的用户总数还发现,成为潜在客户的访问者数量增加了 15%(“访问者转化率”),而光顾购物车的用户数量增加了 11%。

在超过 70% 的网页上,初始视口中的最大元素涉及一张图片,这些元素既可以是独立的 <img> 元素,也可以是有背景图片的元素。换句话说,页面 70% 的 LCP 得分取决于图片性能。了解原因无需太多想象:引人注目的大图片和徽标很可能位于“首屏”上。

web.dev 页面的控制台中突出显示的 LCP

您可以采取一些措施来避免 LCP 延迟:首先,切勿为“首屏”图片指定 loading="lazy",因为将请求延迟到网页呈现后可能会对您的 LCP 得分产生巨大的负面影响。其次,使用 fetchpriority="high" 可以告知浏览器,相应图片的传输的优先级应高于网页上其他位置的图片。

充分谨记这些规则之后,要提高网页的 LCP 得分,最重要的办法就是减少传输和呈现这些图片所需的时间。为此,您需要尽可能缩减图片来源的大小和效率(当然,不牺牲质量),并确保用户只会获得最适合其浏览环境的图片素材资源。

总结

图片素材资源对用户带宽的消耗最大,因为传输渲染网页所需的所有其他素材资源都会占用带宽。在周围的页面布局渲染期间和之后,图片会给感知性能带来重大问题。简而言之:图片素材资源会造成损害

这可能令人望而生畏,虽然单就性能而言,“网页要少一些图片会更好”的确是正确的,但这也会给用户带来很大的负面影响。图片是 Web 的重要组成部分,您不应仅为了性能就牺牲有意义的内容的质量。

在本课程的其余部分,您将了解为我们的图片素材资源提供支持的技术,以及在不影响质量的情况下减轻其性能影响的技术。