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

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

数据压缩基础知识

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

为了实现最佳性能,您需要结合使用以下所有技术:

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

缩减数据大小的过程就是数据压缩。许多人致力于算法、技术和优化措施,以提高压缩比、压缩速度和各种压缩算法所需的内存。

关于数据压缩的全面讨论超出了本指南的范围。但重要的是,您可以大致了解压缩的工作原理,以及可用于减小网页所需各种资源大小的技术。

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

# 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. 消息可能包含标头,这些标头是显示在消息开头的键值对(在上述示例中由 ":" 分隔)。headers
  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. 自定义页面呈现方式。
  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 请求标头中公布对这两种压缩方式的支持。
  • 您的服务器必须配置为启用压缩功能。默认情况下,Web 服务器软件通常会让模块压缩基于文本的资源。
  • gzip 和 Brotli 都可以通过调整压缩级别进行微调,以提高压缩比。对于 gzip,压缩设置介于 1 到 9 之间,9 表示最佳值。对于 Brotli,此范围为 0 到 11,其中 11 是最佳值。但是,压缩设置越高,需要的时间越长。对于动态压缩的资源(即在收到请求时),位于中间范围的设置往往可在压缩比和速度之间实现最佳平衡。但是,您可以进行静态压缩,也就是提前压缩响应,因此可以使用每种压缩算法可用的最积极压缩设置。
  • 内容分发网络 (CDN) 通常对符合条件的资源提供自动压缩功能。CDN 还可以为您管理动态和静态压缩,从而为您省去了压缩方面的一个麻烦。

gzipBrotli 是常用的压缩工具,可应用于任何字节流。在后台,它们会记住之前检查过的文件内容,随后尝试高效地查找和替换重复的数据片段。

在实践中,gzip 和 Brotli 对基于文本的内容效果最佳,通常对于较大的文件,压缩率可高达 70-90%。但是,如果运行这些已使用替代算法压缩的算法资源(例如大多数使用无损或有损压缩技术的图片格式),则收效甚微或根本无法提升。

所有现代浏览器在 Accept-Encoding HTTP 请求标头中均通告支持 gzip 和 Brotli。但是,托管服务提供商有责任确保正确配置 Web 服务器,以便在客户端请求时提供压缩的资源。

文件 算法 未经压缩的大小 压缩后的大小 压缩比
Angular-1.8.3.js 布罗特利 1346 KiB 256 KiB 81%
Angular-1.8.3.js gzip 1346 KiB 329 KiB 76%
Angular-1.8.3.min.js 布罗特利 173 KiB 53 KiB 69%
Angular-1.8.3.min.js gzip 173 KiB 60 KiB 65%
jquery-3.7.1.js 布罗特利 302 KiB 69 KiB 77%
jquery-3.7.1.js gzip 302 KiB 83 KiB 73%
jquery-3.7.1.min.js 布罗特利 85 KiB 27 KiB 68%
jquery-3.7.1.min.js gzip 85 KiB 30 KiB 65%
lodash-4.17.21.js 布罗特利 531 KiB 73 KiB 86%
lodash-4.17.21.js gzip 531 KiB 94 KiB 82%
lodash-4.17.21.min.js 布罗特利 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。

启用压缩是最简单、最有效的优化实现之一。如果您的网站没有充分利用这一功能,那么您将错失提升用户性能的大好机会。幸运的是,许多 Web 服务器会提供默认配置来实现这项重要优化,特别是 CDN 在实现这种配置时非常有效地以平衡压缩速度和比率的方式来实现。

要想快速了解压缩功能的实际效果,请打开 Chrome 开发者工具,打开 Network 面板,加载您选择的页面,然后观察网络面板的最底部。

开发者工具读出实际大小与传输大小。
表示所有页面资源的传输大小(即压缩后)与它们的实际大小(如 Chrome 开发者工具的网络面板中所示)。

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

  • 请求数量,即为页面加载的资源数量。
  • 所有请求的传输大小。这表示对网页的任何资源应用的压缩效果。
  • 所有请求的资源大小。这表示该网页的资源在解压缩后的大小。

对核心网页指标的影响

除非有反映这些改进的指标,否则无法衡量性能改进。核心网页指标计划旨在创建可反映实际用户体验的指标并提高用户对它们的认知度。这与一些无法明确反映用户体验质量的指标(例如简单的网页加载时间)相反。

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

  • 经过缩减和压缩的 HTML 资源可以改善相应 HTML 的加载和子资源的可检测性,从而改善这些 HTML 的加载效果。这有利于网页的 Largest Contentful Paint (LCP)。虽然可以使用 rel="preload" 等资源提示来影响资源的可检测性,但使用过多提示可能会导致带宽争用问题。通过确保压缩导航请求的 HTML 响应,预加载扫描程序可以尽快发现其中的资源。
  • 通过使用压缩,某些 LCP 候选版本也可以更快地加载。例如,对于作为 LCP 候选内容的 SVG 图片,可以通过基于文本的压缩来缩短其资源加载时间。这与您对其他图片类型(通过其他压缩方法进行固有压缩,例如 JPEG 图片如何使用有损压缩)进行的优化不同。
  • 此外,文本节点也可以是 LCP 候选项。本指南中描述的技术取决于您是否在网页上使用网页字体进行文本。如果您使用网页字体,请遵循网页字体优化最佳实践。但是,如果您使用的不是网页字体,而是显示无需任何资源加载时间的系统字体,那么缩减和压缩 CSS 可以缩短其加载时间,这意味着可以更快渲染潜在的 LCP 文本节点。

总结

如何优化基于文本的资源的编码和传输是基本的性能概念,但意义重大。请务必尽一切可能确保符合缩减和压缩条件的资源从这些优化中受益。

更重要的是,确保这些流程是自动完成的。如需缩减大小,请使用打包器对符合条件的资源进行缩减。请确保您的 Web 服务器配置支持压缩,但除此之外,请使用可用的最有效的压缩。为了尽可能简化压缩过程,请使用 CDN 自动进行压缩,因为它们不仅可以为您压缩资源,还可以非常快速地压缩资源。

通过将这些基准性能概念整合到您网站的架构中,您可以确保性能优化工作有良好的基础,并且后续优化可以建立在良好的基准实践的基础之上。