多媒体:图像

媒体(即图片和视频)占普通网站下载字节的 70% 以上。就下载性能而言,消除媒体并减小文件大小是唾手可得的成果。本文着眼于优化图片和视频以提高 Web 性能。

预备知识 已安装基本软件,并具备 客户端 Web 技术 的基础知识。
目标 了解各种图片格式、它们对性能的影响,以及如何减少图片对整体页面加载时间的影响。

注意: 这是关于优化 Web 多媒体传输的高级介绍,涵盖了一般原则和技术。有关更深入的指南,请参阅 https://webdev.ac.cn/learn/images

为什么要优化多媒体?

对于普通网站,51% 的带宽来自图片,其次是视频占 25%,因此可以肯定地说,处理和优化多媒体内容非常重要。

你需要考虑数据使用情况。许多人使用有流量上限的数据套餐,甚至按需付费,他们实际上是按兆字节付费的。这也不是一个新兴市场问题。根据 OFCOM 国家和地区技术追踪器 - 2018 年上半年 (PDF) 的数据,截至 2018 年,英国仍有 24% 的人使用按需付费套餐。

你还需要考虑内存,因为许多移动设备的 RAM 有限。重要的是要记住,图片下载后需要存储在内存中。

优化图片传输

尽管图片下载是最大的带宽消费者,但它对感知性能的影响远低于许多人的预期(主要是因为页面文本内容会立即下载,用户可以看到图片随着它们的到来而渲染)。然而,为了获得良好的用户体验,访问者尽快看到它们仍然很重要。

加载策略

大多数网站最大的改进之一是懒加载首屏以下区域的图片,而不是在初始页面加载时全部下载,无论访问者是否会滚动查看它们。浏览器通过 <img> 元素上的 loading="lazy" 属性提供此功能,还有许多客户端 JavaScript 库可以做到这一点。

除了加载图片子集之外,您还应该查看图片本身的格式

  • 您是否正在加载最优的文件格式?
  • 您是否已很好地压缩图片?
  • 您是否正在加载正确的尺寸?

最优格式

最优文件格式通常取决于图片的特性。

注意: 有关图片类型的一般信息,请参阅图片文件类型和格式指南

SVG 格式更适用于颜色少且非照片级的图片。这需要以矢量图形格式提供源文件。如果此类图片仅以位图形式存在,则PNG 将是首选的备用格式。此类图案的示例有标志、插图、图表或图标(注意:SVG 远优于图标字体!)。这两种格式都支持透明度。

PNG 可以以三种不同的输出组合保存

  • 24 位颜色 + 8 位透明度 — 以牺牲大小为代价提供全色准确度和平滑透明度。您可能希望避免这种组合,转而使用 WebP(参见下文)。
  • 8 位颜色 + 8 位透明度 — 提供不超过 255 种颜色,但保持平滑透明度。大小不会太大。这些是您可能想要的 PNG。
  • 8 位颜色 + 1 位透明度 — 提供不超过 255 种颜色,并且只提供每像素无透明或完全透明,这使得透明边界显得生硬和锯齿状。大小很小,但代价是视觉保真度。

一个很好的 SVG 优化在线工具是 SVGOMG。对于 PNG,有 ImageOptim onlineSquoosh

对于不带透明度的摄影图案,有更广泛的格式可供选择。如果您想安全起见,那么您会选择经过良好压缩的 Progressive JPEG。Progressive JPEG 与普通 JPEG 不同,它会渐进式渲染(因此得名),这意味着用户会看到一个低分辨率版本,随着图片下载,清晰度会逐渐提高,而不是图片以全分辨率从上到下加载,甚至只在完全下载后才渲染。一个好的压缩器将是 MozJPEG,例如,可以在在线图片优化工具 Squoosh 中使用。75% 的质量设置应该会产生不错的效果。

其他格式在 JPEG 的压缩能力方面有所改进,但并非所有浏览器都支持

  • WebP — 图片和动图的绝佳选择。WebP 提供比 PNG 或 JPEG 更好的压缩,并支持更高的色深、动画帧、透明度等(但不支持渐进式显示)。除 macOS Big Sur 或更早版本的 Safari 14 之外,所有主流浏览器都支持。

    注意: 尽管 Apple 宣布 Safari 14 支持 WebP,但 Safari 16.0 之前的版本在 macOS 桌面版本 11/Big Sur 之前无法成功显示 .webp 图片。iOS 14 的 Safari 确实 成功显示 .webp 图片。

  • AVIF — 由于高性能和免版税图片格式(甚至比 WebP 更高效,但支持范围不广),是图片和动画图片的不错选择。它现在受 Chrome、Edge、Opera 和 Firefox 支持。Squoosh 是将以前的图片格式转换为 AVIF 的良好在线工具。

  • JPEG2000 — 曾是 JPEG 的继任者,但仅在 Safari 中受支持。也不支持渐进式显示。

考虑到 JPEG-XR 和 JPEG2000 的狭窄支持,以及解码成本的考量,JPEG 唯一的有力竞争者是 WebP。这就是为什么你也可以以这种格式提供你的图片。这可以通过带有 type 属性<source> 元素辅助的 <picture> 元素来完成。

如果所有这些听起来有点复杂或对您的团队来说工作量太大,那么还有一些在线服务可以作为图片 CDN 使用,它们会根据请求图片的设备或浏览器的类型自动提供正确的图片格式。流行的选择包括 CloudinaryImage EngineImageKitimgix

最后,如果您想在页面中包含动画图片,请注意 Safari 允许在 <img><picture> 元素中使用视频文件。这些还允许您为所有其他现代浏览器添加 Animated WebP

html
<picture>
  <source type="video/mp4" src="giphy.mp4" />
  <source type="image/webp" src="giphy.webp" />
  <img src="giphy.gif" alt="A GIF animation" />
</picture>

提供最优尺寸

在图片传输中,“一刀切”的方法不会产生最佳结果,这意味着对于小屏幕,您会希望提供分辨率较小的图片,反之对于大屏幕也是如此。除此之外,您还会希望为那些拥有高 DPI 屏幕(例如“Retina”)的设备提供更高分辨率的图片。因此,除了创建大量中间图片变体之外,您还需要一种方法来向正确的浏览器提供正确的文件。这就是您需要使用 media 和/或 sizes 属性来升级您的 <picture><source> 元素的地方。响应式图片做得好:<picture>srcset 指南 详细解释了如何组合所有这些属性。

关于高 dpi 屏幕,需要记住两个有趣的效应是

控制图片下载的优先级(和顺序)

将最重要的图片比不那么重要的图片更快地呈现给访问者可以提高感知性能。

首先要检查的是您的内容图片是否使用 <img><picture> 元素,并且您的背景图片是否在 CSS 中使用 background-image 定义——<img> 元素中引用的图片比背景图片具有更高的加载优先级。

其次,随着优先级提示的采用,您可以通过在图片标签中添加 fetchPriority 属性来进一步控制优先级。图片上优先级提示的一个示例用例是轮播图,其中第一张图片的优先级高于后续图片。

渲染策略:防止图片加载时出现卡顿

由于图片是异步加载的,并在首次绘制后继续加载,如果它们的尺寸在加载前未定义,它们可能会导致页面内容重排。例如,当图片加载时文本被向下推。因此,设置 widthheight 属性很重要,这样浏览器就可以在布局中为它们保留空间。

当 HTML <img> 元素中包含图片的 widthheight 属性时,浏览器可以在图片加载之前计算图片的宽高比。此宽高比用于保留显示图片所需的空间,减少甚至防止图片下载并绘制到屏幕时发生布局偏移。减少布局偏移是良好用户体验和 Web 性能的重要组成部分。

浏览器在解析 HTML 时开始渲染内容,通常在所有资源(包括图片)下载完成之前。包含尺寸使浏览器能够为每张图片预留一个大小正确的占位符框,以便在首次渲染页面时加载图片时显示。

Two screenshots the first without an image but with space reserved, the second showing the image loaded into the reserved space.

如果没有 widthheight 属性,则不会创建占位符空间,从而在图片加载后渲染页面时在页面中产生明显的卡顿或布局偏移。页面重排和重绘是性能和可用性问题。

CLS 指标衡量页面加载时的卡顿程度,即视口中可见内容移动了多少以及移动了多少。导致 CLS 差的主要罪魁祸首是未声明尺寸的可替换元素,当资源加载时它们会重排,包括没有尺寸或aspect-ratio的图片、广告、嵌入和 iframe,以及网页字体。

在响应式设计中,当容器比图片窄时,通常使用以下 CSS 来防止图片溢出其容器

css
img {
  max-width: 100%;
  height: auto;
}

虽然这对于响应式布局很有用,但当没有包含宽度和高度信息时,会导致卡顿和糟糕的 CLS,因为如果在解析 <img> 元素但图片尚未加载之前没有高度信息,此 CSS 实际上会将高度设置为 0。当图片在页面最初渲染到屏幕后加载时,页面会重排并重新绘制,从而创建布局偏移,因为它为新确定的高度创建了空间。

浏览器有一种在实际图像加载之前确定图像大小的机制。当 <img><video><input type="button"> 元素设置了 widthheight 属性时,其宽高比会在加载之前计算出来,并可供浏览器使用,使用提供的尺寸。

然后使用宽高比来计算高度,因此,正确的尺寸将应用于 <img> 元素,这意味着上述卡顿不会发生,或者如果列出的尺寸在图像加载时不是完全准确,则卡顿会最小化。

宽高比仅用于在图像加载时预留空间。一旦图像加载完成,加载图像的固有宽高比或 `aspect-ratio` 属性的值将取代属性中的宽高比。这确保了即使属性尺寸不准确,它也能以正确的宽高比显示。

尽管过去十年的开发者最佳实践可能建议省略 HTML <img> 元素的 widthheight 属性,但由于宽高比映射,包含这两个属性被认为是开发者最佳实践。

对于任何背景图片,务必设置一个 background-color 值,以便在图片下载之前,任何叠加的内容仍然可读。

总结

在本节中,我们探讨了图片优化。您现在对如何优化平均网站总带宽的一半有了一个大致的了解。这只是消耗用户带宽并减慢页面加载速度的媒体类型之一。接下来让我们看看视频优化,它解决了接下来的 20% 带宽消耗。