优化基于文本的资源的编码和传输大小

除了避免不必要的资源下载,在提高网页加载速度上您可以采取的最有效措施就是,通过优化和压缩其余资源来最大限度减小总下载大小。

在您设置网站以避免下载任何未使用的资源后,下一步就是对浏览器需要下载的所有剩余符合条件的资源进行压缩。根据资源类型(文本、图片、字体等),有多种不同的技术可供选择:可在 Web 服务器上启用的通用工具、针对特定内容类型的预处理优化以及需要开发者输入的资源专用优化。

实现最佳性能需要组合使用以下所有技术:

  • 压缩就是使用更少的位对信息进行编码的过程。
  • 消除不必要的数据总是会产生最好的结果。
  • 有许多不同的压缩技术和算法。
  • 您需要利用各种技术来实现最佳压缩。

缩减数据大小的过程称为数据压缩。许多人致力于算法、技术和优化研究,以期提高各种压缩算法的压缩比率、压缩速度和内存要求。

关于数据压缩的完整讨论远远超出本指南的讨论范围。 但是,概要了解压缩的工作原理以及在减小网页所需各类资产大小方面可供我们利用的技术,仍具有重要意义。

为说明这些技术的核心原理,我们看看如何优化一种简单的短信格式(不过是我们专为此示例编造的格式):

# Below is a secret message, which consists of a set of headers in
# key-value format followed by a newline and the encrypted message.
format: secret-cipher
date: 08/25/16
AAAZZBBBBEEEMMM EEETTTAAA
  1. 消息可能包含任意注释(有时称为注释),以“#”前缀表示。注释不会影响消息的含义或行为。
  2. 消息可能包含标头,即显示在消息开头的键值对(在前面的示例中以 ":" 分隔)。
  3. 短信带有文本负载。

怎样才能减小先前消息(从 200 个字符开始)的大小?

  1. 注释是很有意思,但它并不影响短信的含义。因此您可以在传送短信时将其去掉。
  2. 有一些好的技术可以高效对标头进行编码。例如,如果您知道所有短信都包含“format”和“date”,您就可以将它们转换成短整型 ID 并只发送这些 ID。不过,情况可能不是这样,因此最好暂时不予理会。
  3. 载荷仅为文本。尽管我们不知道其实际内容(显然,它使用的是一种 "secret-cipher"),但只需看一看文本内容,就会发现其中存在大量多余内容。或许,您可以不发送重复的字母,而是直接对重复的字母计数,再对它们进行更高效的编码。例如,"AAA" 会变为 "3A",表示三个 A 的序列。

组合使用这些技术可以实现下面的结果:

format: secret-cipher
date: 08/25/16
3A2Z4B3E3M 3E3T3A

新短信的长度为 56 个字符,这意味着您已将原有短信压缩了 72%。这是一个显著的减少!

下面是一个小示例,展示了压缩算法如何有效地缩减基于文本的资源的传输大小。在实践中,压缩算法远比前面的示例所示更为复杂。在 Web 上,压缩算法可用于显著缩短资源的下载时间。通过对基于文本的资源应用压缩,网页可以缩短资源的加载时间,这样,用户就可以比未压缩时更快地看到这些资源的效果。

缩减大小:预处理和针对特定上下文的优化

这里讨论的第一种技术是缩减大小。虽然缩减严格来说不是压缩算法,但它是一种移除源代码中不必要和多余字符的方法,可让资源更易于人阅读。不过,在正式版网站上维护该源代码的功能时,不需要这种可读性,而且这可能会延迟 Web 上资源的加载。

缩减大小是一种针对特定内容的优化,可以显著缩减所提供资源的大小,这种优化最好在构建和部署流程中加以应用。例如,捆绑器就是一种常用的软件类型,可以在将新的生产代码部署到网站之前自动缩减资源的大小。

压缩冗余或不必要数据的最佳方法是将其消除。不过,您不能随意删除数据。不过,在某些环境中,我们可能对数据格式及其属性有内容特定了解,往往可以在不影响其实际含义或功能的情况下显著减小负载的大小。

<html>
  <head>
    <style>
      /* awesome-container is only used on the landing page */
      .awesome-container {
        font-size: 120%;
      }

      .awesome-container {
        width: 50%;
      }
    </style>
  </head>
  <body>
    <!-- awesome container content: START -->
    <div>
      This is my awesome container, and it is <em>so</em> awesome.
    </div>
    <!-- awesome container content: END -->
    <script>
      awesomeAnalytics(); // Beacon conversion metrics
    </script>
  </body>
</html>

以上面这个 HTML 代码段及其包含的三个不同内容类型为例:

  1. HTML 标记。
  2. CSS,用于自定义页面的呈现方式。
  3. 为互动和其他高级网页功能提供支持的 JavaScript。

其中的每一个内容类型针对构成有效内容的元素都具有不同的规则,在注释指示等方面也具有不同的规则。不过,仍有一个问题:“如何减小此页面的大小?”

  • 代码注释是开发者最好的朋友,但浏览器不需要看到它们!删除 CSS (/* ... */)、HTML (<!-- ... -->) 和 JavaScript (// ...) 注释可缩减网页及其子资源的总传输大小。
  • “智能”的 CSS 压缩程序可能会注意到,我们在为 .awesome-container 定义规则的方式效率低下,会在不影响任何其他样式的情况下将两个声明折叠为一个,从而节省更多字节。在大量 CSS 规则中,移除这种冗余可能会积少成多,但可能无法积极应用,因为不同上下文(例如在媒体查询中)通常会有重复的选择器。
  • 空格和制表符能够在 HTML、CSS 和 JavaScript 中给开发者提供方便。 一个额外的压缩工具可以去掉所有制表符和空格。与其他重复信息删除技术不同,您可以积极应用此类优化,只要此类空格或制表符对于网页的呈现即可 - 例如,您可以保留 HTML 文档中文本各行中的空格,因为它们可确保用户实际看到的内容可读。
<html><head><style>.awesome-container{font-size:120%;width:50%}</style></head><body><div>This is my awesome container, and it is <em>so</em> awesome.</div><script>awesomeAnalytics()</script></body></html>

应用上述步骤后,网页字符数从 516 缩减到 204,缩减率约为 60%。当然,它不太易读,但它不必易读就能使用。借助现代开发实践,您还可以将格式良好且易于阅读的源代码版本与要发布到生产环境的经过充分优化的代码分开。结合使用源代码映射(可提供经过转换的生产代码的可读表示,让您更轻松地排查生产环境中的 bug)后,您既可以获得良好的开发者体验,又可以出于用户体验的考虑优化性能。

前面的示例说明了一个重要问题:通用压缩工具(例如,旨在压缩任意文本的工具)可以非常有效地压缩前面的示例中的网页,但它永远不会知道如何剥离注释、折叠 CSS 规则或执行其他数十种特定于内容的优化。因此,预处理、缩减和其他环境感知型优化至关重要。

同理,可以将以上技术运用到基于文本的资产以外的其他领域。图片、视频和其他内容类型都包含其自己的元数据形式和各种载荷。例如,每当您使用相机拍摄照片时,照片的文件通常也会嵌入大量额外的信息:相机设置、位置等等。视具体应用而定,这些数据可能很关键(例如照片分享网站),也可能毫无用处。您应考虑是否有必要将其移除。事实上,每一幅图像的这些元数据加起来可能多达数万字节。

简而言之,作为优化资源效率的第一步,您需要构建不同内容类型的清单,并考虑可以进行哪些类型的内容特定优化来减小其大小。然后,在您确定具体的优化后,通过将其加入构建和发布步骤来自动执行这些优化,以便确保对正式版的每个新版本都一致地应用这些优化。

使用压缩算法压缩文本

减小基于文本的素材资源大小的下一步是,对其应用压缩算法。它更进一步,在将基于文本的载荷发送给用户之前,会在基于文本的载荷中积极搜索可重复的模式,并在载荷到达用户的浏览器后对其进行解压缩。这样一来,这些资源的数量会进一步大幅减少,下载时间也会随之缩短。

  • gzip 和 Brotli 是常用的压缩算法,在基于文本的资源(CSS、JavaScript、HTML)上效果最佳。
  • 所有现代浏览器都支持 gzip 和 Brotli 压缩,并且会在 Accept-Encoding HTTP 请求标头中通告对这两者的支持。
  • 您的服务器必须配置为启用压缩功能。默认情况下,网络服务器软件通常会启用模块以此方式压缩基于文本的资源。
  • 您可以通过调整压缩级别,对 gzip 和 Brotli 进行微调,以提高压缩比率。对于 gzip,压缩设置范围为 1 到 9,其中 9 是最佳设置。对于 Brotli,此范围为 0 到 11,其中 11 为最佳。但是,压缩设置越高,需要的时间就越长。对于动态压缩(即在请求时压缩)的资源,中间范围的设置通常可在压缩比率和速度之间取得最佳平衡。不过,可以进行静态压缩,即提前压缩响应,因此可以使用适用于每种压缩算法的最激进的压缩设置。
  • 内容分发网络 (CDN) 通常会自动压缩符合条件的资源。CDN 还可以为您管理动态和静态压缩,让您不必再为压缩方面的问题操心。

gzipBrotli 是可以应用于任何字节流的常用压缩程序。它们会在后台记忆文件中之前检查过的一些内容,然后尝试以高效方式查找并替换重复的数据片段。

实际上,gzip 和 Brotli 对基于文本的内容效果最佳,对于较大的文件,其压缩率通常高达 70-90%。不过,如果对已经使用替代算法压缩过的资源(例如,使用无损或有损压缩技术的大多数图片格式)运行这些算法,则效果甚微,甚至毫无效果。

所有现代浏览器都会在 Accept-Encoding HTTP 请求标头中通告对 gzip 和 Brotli 的支持。不过,托管服务提供商有责任确保网络服务器得到正确配置,能够在客户端请求时提供压缩过的资源。

文件 算法 未经压缩的大小 压缩后的大小 压缩比
Angular-1.8.3.js 布罗特利 1,346 KiB 256 KiB 81%
angular-1.8.3.js gzip 1,346 KiB 329 KiB 76%
angular-1.8.3.min.js Brotli 173 KiB 53 KiB 69%
angular-1.8.3.min.js gzip 173 KiB 60 KiB 65%
jquery-3.7.1.js Brotli 302 KiB 69 KiB 77%
jquery-3.7.1.js gzip 302 KiB 83 KiB 73%
jquery-3.7.1.min.js Brotli 85 KiB 27 KiB 68%
jquery-3.7.1.min.js gzip 85 KiB 30 KiB 65%
lodash-4.17.21.js Brotli 531 KiB 73 KiB 86%
lodash-4.17.21.js gzip 531 KiB 94 KiB 82%
lodash-4.17.21.min.js Brotli 71 KiB 23 KiB 68%
lodash-4.17.21.min.js gzip 71 KiB 25 KiB 65%

上表显示了 Brotli 和 gzip 压缩对几种知名 JavaScript 库可实现的压缩率。节省量介于 65% 到 86% 之间,具体取决于文件和算法。Brotli 和 gzip 的每个文件都应用了最高压缩级别,以供参考。尽可能使用 Brotli,而不是 gzip。

启用压缩是最简单且最有效的优化之一。如果您的网站没有加以利用,您将错失为用户提升性能的大好机会。幸运的是,许多网络服务器都提供了可实现此重要优化的默认配置,而 CDN 在以平衡压缩速度和压缩比的方式实现此优化方面尤其有效。

要想快速了解压缩效果,一种方法是打开 Chrome 开发者工具,打开 Network 面板,加载您选择的页面,然后观察 Network 面板的最底部。

DevTools 中显示的实际大小与传输大小。
表示所有网页资源的传输大小(即压缩大小)与其实际大小(如 Chrome DevTools 的“Network”面板中所示)。

与上图一样,您应该会看到以下明细:

  • 请求数,即为网页加载的资源数。
  • 所有请求的传输大小。这反映了应用于网页任何资源的压缩效果。
  • 所有请求的资源大小。该指标反映了网页资源在解压缩后的大小。

对 Core Web Vitals 的影响

除非有反映这些改进的指标,否则无法衡量效果改进。Core Web Vitals 计划旨在创建和提高对反映实际用户体验的指标的认识。这与一些指标(例如简单的网页加载时间)形成鲜明对比,这些指标无法明确反映用户体验质量。

将本指南中介绍的优化措施应用于您网站上的资源后,对核心 Web 指标的影响可能会因优化的资源和涉及的指标而异。不过,在以下一些情况下,应用这些优化措施可以改善您网站的核心 Web 指标:

  • 经过缩减和压缩的 HTML 资源可以提高该 HTML 的加载速度、其子资源的可检测性,从而提高子资源的加载速度。这对网页的 Largest Contentful Paint (LCP) 有益。虽然 rel="preload" 等资源提示可用于影响资源的可检测性,但使用太多资源提示可能会导致带宽争用问题。通过确保导航请求的 HTML 响应已压缩,预加载扫描器可以尽快发现其中的资源。
  • 通过使用压缩功能,还可以更快地加载某些 LCP 候选项。例如,对于是 LCP 候选项的 SVG 图片,可以通过基于文本的压缩来缩短资源加载时长。这不同于您对其他图片类型进行的优化;其他图片类型通过其他压缩方法固有地进行压缩,例如 JPEG 图片如何使用有损压缩。
  • 此外,文本节点也可以是 LCP 候选项。本指南中介绍的技术的运作方式取决于您是否在网页上使用 Web 字体。如果您使用的是网页字体,则需要遵循网页字体优化最佳实践。不过,如果您使用 Web 字体,而是使用在显示时不会产生任何资源加载时长的系统字体,则缩减和压缩 CSS 会缩短此时长,这意味着系统可以更快地渲染潜在的 LCP 文本节点。

总结

如何优化基于文本的资源的编码和传输是基准性能概念,但具有重大影响。请务必尽最大努力确保符合缩减和压缩条件的资源能够从这些优化中受益。

更重要的是,确保这些流程已实现自动化。对于缩减,请使用捆绑工具对符合条件的资源应用缩减。确保您的网站服务器配置支持压缩,但更重要的是,使用可用的最有效的压缩。为尽可能简化此过程,请使用 CDN 为您自动压缩,因为它们不仅可以为您压缩资源,而且可以非常快速地完成压缩。

将这些基准性能概念融入网站架构中,您可以确保在良好的基础上进行性能优化,并在良好的基准实践基础上进行后续优化。