本文首发于微信公众号:大迁世界, 我的微信:qq449245884,我会第一时间和你分享前端行业趋势,学习途径等等。
更多开源作品请看 GitHub https://github.com/qq449245884/xiaozhi ,包含一线大厂面试完整考点、资料以及我的系列文章。

目前,图像是Web中规模最大的资源,无论是总传输大小还是每页请求数量。截至2022年6月,中位数网页的总传输大小约为2MB,其中图像仅占近一半。可以说,优化图像请求可能是我们可以进行的最大性能优化。

推迟图像请求

首先,我们来看一个重要的属性:loading="lazy":

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

使用这个属性可能很简单,但它对性能的影响可以非常有效的:如果图像不出现在视口中,那么就不会发出请求,并且也不会浪费带宽。

然而,有一个问题:推迟请求意味着不能利用浏览器尽早请求图像。如果在布局顶部的 img 元素上使用 loading="lazy",因此在页面首次加载时更有可能出现在用户的视口中,则这些图像对用户来说可能显示得更慢。

优先提示

loading 属性是Web 标准努力的一个成果,让开发人员对浏览器请求的优先级更多地控制。

大家可能知道浏览器的基本请求优先级方法:例如,对文档 <head> 中的外部 CSS 文件的请求会优先执行并阻止渲染,而对于在 </body> 之前的外部 JavaScript 文件的请求被延迟到渲染完成。如果 <img> 上的 loading 属性的值是 'lazy',则相关的图像请求将被延迟,直到浏览器确定它将显示给用户为止。否则,该图像将具有与页面上任何其他图像相同的优先级。

实验性的 fetchpriority 属性让开发人员对资源的优先级更加精细地控制,允许我们相对于同类资源标记资源为 'high''low' 优先级。

fetchpriority 的使用场景与 loading 属性相似,但覆盖面更广。例如,我们可以仅在用户交互后显示的图像上使用 fetchpriority="low"(无论该图像是否在用户的视口中),以优先处理页面上的可见图像,或使用 fetchpriority="high" 优先处理我们知道页面渲染后立即可见的视口。

注意,fetchpriorityloading 不同,它不会从根本上改变浏览器的行为。它不会指示浏览器在其他资源之前加载某些资源,而是为它对请求资源的决策提供了重要的背景。

衡量图像的影响

在优化图像时,对用户的感知性能通常更为重要,并且比仅仅测量数据传输大小更难衡量。

Web Vitals 提供可衡量的、可操作的指标和指导,以提高用户体验,突出了诸如网页服务器响应时间过慢、渲染问题和交互延迟等问题。核心 Web Vitals 是这些目标的一个子集,专注于用户对单个页面的直接体验——一组技术测量,它们共同决定了体验对用户来说有多快。

Cumulative Layout Shift

累积布局位移(CLS)是视觉稳定性的度量。它是衡量页面内容布局在加载资源并渲染页面时如何移动的指标。任何使用了Web的人都有过因页面在某个延迟的字体或图片资源突然渲染而跳动而导致在长文章中的位置丢失的经历,或者把交互元素移动到指针之外的位置。

CLS高的情况最多只是一种麻烦,在最坏的情况下是导致用户错误的原因,例如,在用户单击时“取消”按钮移动到先前被“确认”按钮占用的位置。

由于加载时间较长以及它们在布局中所占的空间,因此图像是导致 CLS分数较高的常见原因。

事例:https://codepen.io/web-dot-de...

由于现代浏览器的相对较新的变化,避免因图像导致的高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;
}

在以前的情况中,删除了<img>元素上的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高分。

事例:https://codepen.io/web-dot-de...

重要的是,这种方法没有任何缺点,因为它依赖于长期存在的浏览器行为,任何支持基本CSS的浏览器都将像往常一样工作,HTML属性中的 heightwidth 属性将被样式覆盖。

虽然 widthheight属性通过保留图像所需的布局空间来避免CLS问题,但会向用户渲染空白或低质量的占位符,等待图像传输和党建也不理想。尽管可以采取一些措施减少加载慢的图像的可测量和可察觉影响,但向用户更快地党建完整图像的唯一方法是通过减小传输大小。

Largest Contentful Paint

最大内容绘制(LCP)衡量用户可视视口中最大“内容绘制”元素渲染所需的时间,即占可见页面最大百分比的内容元素。在表面上,这个指标似乎过于具体,但它实际上代表了从用户的角度看到页面大部分内容已被渲染的时间。 LCP是(感知的)性能的关键指标

DOMContentLoadedwindow.onload事件等指标可以用于确定当前页面加载的过程在技术上已完成,但它们不一定对应于用户对页面的体验。在用户视野外的元素的渲染略有延迟,将被计入这些指标中,但可能完全被现实世界的用户忽略。长LCP意味着用户对页面的第一印象是页面缓慢或彻底停滞。

用户对 LCP 的感知对用户体验产生直接影响。去年 Vodafone 进行的一项实验发现,LCP 提高 31% 不仅导致销售额增加了 8%,这本身就是一个很好的结果,但他们的总用户中,潜在客户数量增加了 15%,访问购物车的用户数量增加了 11%

70% 以上的网页中,初始视口中的最大元素涉及图像,可以是单独的 <img> 元素,也可以是具有背景图像的元素。换句话说,70% 的页面的 LCP 分数都是基于图像性能。不难想象,大而引人注目的图像和标志很可能会在“above the fold”被找到。

image.png

我们可以采取一些步骤来避免 LCP 延迟:首先,不要在above the fold 图像上指定 loading="lazy",因为延迟请求直到页面渲染完成将可能对 LCP 分数产生巨大的负面影响。其次,使用 fetchpriority="high" 可以告诉浏览器该图像的传输应该优先于页面上的其他图像。

牢记这些规则,提高页面 LCP 分数的最重要的事情是减少传输和渲染这些图像所需的时间。为了实现这一目标,您要保持图像源尽可能小和高效(当然不会牺牲质量),并确保用户仅获取对他们的浏览上下文最有意义的图像资源。

总结

图像资源是对用户带宽的最大流失,这是从传输每个渲染页面所必需的其他资源所消耗的带宽。图像在性能感知方面引入了重要问题,无论是在周围页面布局渲染后还是之前。简而言之:图像资源造成了损害。

尽管如此令人生畏,但是“如果图像少一些,Web的性能就会更好”肯定是仅仅从性能角度来说是正确的,但它也对用户造成了巨大的不利影响。图像是Web的重要组成部分,我们不应该仅为了性能而妥协有意义的内容的质量。

代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug

原文:https://web.dev/learn/images/...

交流

有梦想,有干货,微信搜索 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。

本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试完整考点、资料以及我的系列文章。


王大冶
68k 声望104.9k 粉丝