轻松实现 Web 性能 - Google I/O 2018 特制版

在 2018 年 Google IO 大会上,我们介绍了一系列工具、库和优化技术,它们可帮助您更轻松地提升 Web 性能。在这里,我们将使用 The Oodles Theater 应用进行解释。此外,我们还将讨论预测加载方面的实验以及新的 Guess.js 计划。

Addy Osmani
Addy Osmani
Ewa Gasperowicz

在过去的一年里,我们一直非常忙,努力探索如何让网络更快速、更高效。由此催生了新的工具、方法和库,我们想在这篇文章中与您分享这些新工具、方法和库。第一部分,我们将介绍我们在开发 The Oodles Theater 应用时实际运用的一些优化技巧。第二部分,我们将介绍预测加载方面的实验和新的 Guess.js 计划。

对性能的需求

互联网变得每年越来越重、更沉重。通过查看网络状况,我们可以看到,在移动设备上,某个网页的权重中位数约为 1.5MB,其中大部分是 JavaScript 和图片。

网站规模的不断扩大,以及网络延迟、CPU 限制、渲染阻塞模式或多余的第三方代码等其他因素,造成了复杂的性能问题。

大多数用户都将速度视为其需求中用户体验层级的最顶层。这并不奇怪,因为在网页加载完成之前,您实际上无法执行太多操作。您无法从网页中获得价值,也无法欣赏网页的美感。

用户体验层次结构金字塔式
图 1.速度对用户有多重要?(《Speed Matters》第 3 卷

我们知道性能对用户很重要,但找到开始优化的位置可能也像是一个秘密。幸运的是,有一些工具可以为您提供帮助。

Lighthouse - 性能工作流的基础

Lighthouse 是 Chrome 开发者工具的一部分,可用于审核网站,并为您提供有关如何改进网站的提示。

我们最近发布了许多新的性能审核,它们在日常开发工作流中非常有用。

新的 Lighthouse 审核
图 2.新版 Lighthouse 审核

让我们通过一个实际的例子来探索如何利用它们:Oodles Theater 应用。这是一款小型演示 Web 应用,您可以在其中试用我们喜爱的一些互动式 Google 涂鸦,甚至可以玩一两款游戏。

在构建应用时,我们希望确保它的性能尽可能高。可以从 Lighthouse 报告开始进行优化。

Oodles 应用的 Lighthouse 报告
图 3.Oodles 应用的 Lighthouse 报告

Lighthouse 报告显示我们的应用的初始性能非常糟糕。在 3G 网络上,用户需要等待 15 秒才能首次有意义的绘制,或等待应用进入可交互状态。Lighthouse 突出显示了我们网站中的大量问题,总体性能得分 23 正好反映了这一点。

网页加权约为 3.4MB - 我们迫切需要减少脂肪。

这开启了我们的第一个性能挑战:找出我们可以轻松移除而不会影响整体体验的内容。

效果优化机会

移除不必要的资源

有一些显而易见的内容是可以安全移除的:空白和评论。

缩减大小带来的收益
图 4.缩减 JavaScript 和 CSS 的大小并压缩

Lighthouse 在未缩减的 CSS 和 JavaScript 审查中强调了这一机会。我们在构建流程中使用了 webpack,因此为了缩减大小,我们直接使用了 Uglify JS 插件

缩减大小是一项常见的任务,因此您应该能够针对您碰巧使用的构建流程找到现成的解决方案。

另一方面实用的审核是启用文本压缩。没有理由发送未压缩的文件,而大多数 CDN 现在都支持此功能。

我们以前使用 Firebase Hosting 托管代码,而 Firebase 默认支持 gzip 处理,因此,凭借在合理的 CDN 上托管我们的代码,我们可以免费实现这一点。

虽然 gzip 是一种非常流行的压缩方式,但 ZopfliBrotli 等其他机制也越来越受欢迎。Brotli 在大多数浏览器中都受支持,并且您可以在将资源发送到服务器之前使用二进制文件对资源进行预压缩。

使用高效的缓存策略

下一步,确保不会在必要时发送资源两次。

通过 Lighthouse 中的低效缓存政策审核,我们发现我们可以优化缓存策略,以便恰好实现这一点。通过在我们的服务器中设置 max-ageexpiration 标头,我们可确保用户在重复访问时,能够重复使用之前下载的资源。

理想情况下,您的目标应该是在尽可能最长的时间内以安全的方式缓存尽可能多的资源,并提供验证令牌以高效地重新验证已更新的资源。

移除未使用的代码

到目前为止,我们已经移除了不必要的下载内容中显而易见的部分,那么对于那些不太明显的部分呢?例如未使用的代码。

开发者工具中的代码覆盖率
图 5.检查代码覆盖率

有时,我们会向应用代码中添加实际上不必要的代码。尤其是在以下情况下,这种情况会发生:您的应用开发时间较长,您的团队或依赖项发生变化,有时孤立库会被遗留。我们当时就是这样。

最初,我们使用 Material 组件库来快速设计应用的原型。 后来,我们改用了自定义程度更高的外观和风格,却完全忘记了这个库。 幸运的是,通过代码覆盖率检查,我们从 bundle 中重新发现了它。

您可以在开发者工具中查看代码覆盖率统计信息,包括应用的运行时和加载时间。您可以看到下方的屏幕截图中两条很长的红色条纹 - 我们有超过 95% 的 CSS 未被使用,同时还有大量 JavaScript。

Lighthouse 还在“未使用的 CSS 规则”审核中发现了此问题。显示可以节省超过 400KB我们回到我们的代码,移除了该库的 JavaScript 和 CSS 部分。

如果丢弃 MVC 适配器,我们的样式就会减少到 10KB
图 6.如果丢弃 MVC 适配器,我们的样式就会减少到 10KB!

这使得我们的 CSS 软件包缩减了 20 倍,对于长两行的微小提交而言,效果相当不错。

当然,我们的性能得分提高了,可交互时间也得到了改进。

但是,随着此类更改,仅查看指标和得分是不够的。 移除实际代码绝非没有风险,因此您应始终留意潜在的回归问题。

我们的代码有 95% 未被使用,但某处仍然有这 5% 的代码。显然,我们的一个组件仍在使用该库中的样式,即涂鸦滑块中的小箭头。不过,由于尺寸太小,因此我们可以直接将这些样式手动重新整合到按钮中。

按钮因缺少库而损坏
图 7.一个组件仍在使用已移除的库

因此,如果您移除代码,只需确保部署适当的测试工作流,防止潜在的视觉回归问题即可。

避免网络负载过大

我们知道大型资源会降低网页加载速度。它们可能会使用户付费,对流量套餐产生重大影响,因此请务必留意这一点。

Lighthouse 使用巨大的网络载荷审核检测到我们的部分网络载荷存在问题。

检测网络负载
图 8.检测庞大的网络载荷

在这里,我们看到有超过 3MB 的代码被植入了代码,非常多,尤其是在移动设备上。

在此列表的最顶部,Lighthouse 突出显示了我们有一个 JavaScript 供应商软件包,其中包含 2 MB 的未压缩代码。这也是 webpack 所强调的一个问题。

常言道,最快的请求尚未发出。

理想情况下,您应衡量您向用户投放的每项素材资源的价值,衡量这些素材资源的效果,并决定在初始体验中是否值得实际下线。因为有时这些资源可能会被延迟、延迟加载或空闲期间处理。

在本例中,由于我们要处理大量 JavaScript 软件包,幸运的是,JavaScript 社区拥有丰富的 JavaScript 软件包审核工具。

JavaScript 软件包审核
图 9.JavaScript 软件包审核

我们最先使用的是 webpack 软件包分析器,该工具告诉我们要加入一个名为 unicode 的依赖项,这个依赖项是 1.6 MB 的已解析 JavaScript,所以非常多。

然后,我们进入了编辑器,通过使用 Import Cost Plugin for Visual code,我们能够直观呈现所导入的每个模块的费用。这使我们能够发现哪个组件包含引用此模块的代码。

然后,我们改用另一款工具 BundlePhobia。借助该工具,您可以输入任何 NPM 软件包的名称,并实际看到其压缩后和 gzip 压缩后的大小估计值。我们为目前使用的 Slug 模块找到了一个仅重 2.2kb 的好替代选项,于是我们更换了该模块。

这对我们的广告效果产生了巨大影响。既然有了这项更改,再到发现其他缩减 JavaScript 软件包大小的机会,我们节省了 2.1 MB 的代码。

在将这些软件包的 gzip 压缩和缩减大小考虑在内后,我们发现总体提升了 65%。 我们发现,作为一个过程,我们确实很有必要这样做。

因此,一般情况下,请尽量避免从您的网站和应用中产生不必要的下载内容。 清点您的资产并衡量它们对性能的影响可能产生巨大差异,因此请确保定期审核资产。

通过代码拆分缩短 JavaScript 启动时间

虽然大型网络载荷会对我们的应用产生重大影响,但还有个东西可能也会产生非常大的影响,那就是 JavaScript。

JavaScript 是最昂贵的资源。在移动设备上,如果您发送大量 JavaScript,则可能会延迟用户与界面组件互动的时间。这意味着,用户点按界面时,无需实际发生任何有意义的操作。因此,我们必须了解 JavaScript 成本高昂的原因。

这就是浏览器处理 JavaScript 的方式。

JavaScript 处理
图 10.JavaScript 处理

首先,我们必须下载该脚本。我们有一个 JavaScript 引擎,然后需要解析相应代码、对其进行编译并执行。

现在,在台式机或笔记本电脑(甚至是高端手机)上,这些阶段不会占用大量时间。而在中位数的手机上,此过程可能需要五到十倍的时间这就是导致互动性延迟的原因,因此我们必须尝试减少这一问题。

为帮助您发现应用中的这些问题,我们在 Lighthouse 中引入了一项新的 JavaScript 启动时间审核功能。

JavaScript 启动时间
图 11.JavaScript 启动时间审核

而对于 Oodle 应用,我们则告诉我们,启动了 JavaScript 后,我们花了 1.8 秒的时间。当时的情况是,我们以静态方式将所有路由和组件导入一个单体式 JavaScript 软件包。

解决此问题的一种方法是使用代码拆分。

代码拆分就像披萨一样

代码拆分是一种概念,而不是为用户提供一个整份披萨的 JavaScript 代码,如果您在用户需要时一次只向其提供一块,该怎么办?

代码拆分可在路由级别或组件级别应用。它非常适合与 React、React Loadable、Vue.js、Angular、Polymer、Preact 和多个其他库配合使用。

我们将代码拆分功能整合到了应用中,并从静态导入切换到动态导入,从而让我们能够根据需要异步延迟加载代码。

使用动态导入功能进行代码拆分
图 13.使用动态导入功能进行代码拆分

这样做的影响不仅缩减了软件包的大小,还缩短了 JavaScript 的启动时间。应用耗时缩短至 0.78 秒,使应用速度加快 56%。

一般来说,如果您要打造大量 JavaScript 体验,请务必只将代码发送给用户所需的用户。

您可以利用代码拆分等概念,探索摇树优化等概念,并查看 webpack-libs-optimizations 代码库,了解在您碰巧使用 webpack 时如何缩减库大小。

优化图像

关于图片加载性能的笑话

我们在 Oodle 应用中使用了大量图片。遗憾的是,Lighthouse 对它的热情比我们低了很多。事实上,我们未能通过全部三项与图像相关的审核。

我们忘记优化图片,未正确调整图片大小,并且可以通过使用其他图片格式获得一些好处。

图片审核
图 14.Lighthouse 映像审核

我们首先优化图片。

要进行一次性优化,您可以使用 ImageOptimXNConvert 等可视化工具。

一种自动化程度更高的方法是使用 imagemin 等库向构建流程添加映像优化步骤。

这样,您就可以确保以后添加的图片会自动得到优化。有些 CDN(例如 Akamai)或第三方解决方案(例如 CloudinaryFastlyUploadcare)为您提供了全面的图片优化解决方案,因此您也可以将图片托管在这些服务上。

如果您因为费用或延迟问题不想这样做,可以选择 ThumborImageflow 等项目提供的自托管的替代方案。

优化前后
图 15.优化前后

我们的背景 PNG 在 webpack 中被标为大,这没错。在正确调整其大小,使其适合视口并通过 ImageOptim 运行后,图片的大小会降至 100kb,这是可以接受的。

对网站上的多张图片重复执行此操作可以显著降低网页的整体重量。

使用正确的格式呈现动画内容

GIF 可能会非常昂贵。而出乎意料的是,GIF 格式从一开始就从未计划过用作动画平台。因此,切换到更合适的视频格式可节省大量的文件大小。

在 Oodle 应用中,我们使用 GIF 作为首页上的介绍序列。Lighthouse 称,如果改用更高效的视频格式,我们可以节省 7MB 以上的内存。我们的视频片段的权重约为 7.3 MB,对于任何合理的网站来说都离不开,因此我们将它变成了一个包含两个源文件的视频元素:一个 mp4 和 WebM,以提供更广泛的浏览器支持。

将 GIF 动画替换为视频
图 16.将 GIF 动画替换为视频

我们使用 FFmpeg 工具将动画 GIF 转换为 mp4 文件。WebM 格式可为您提供更大的优惠,ImageOptim API 可以为您进行此类转换。

ffmpeg -i animation.gif -b:v 0 -crf 40 -vf scale=600:-1 video.mp4

得益于这种转化,我们成功地节省了总体重超过 80% 的体重。使内存缩减至约 1MB

尽管如此,1 MB 仍是下推连接线所需的资源,尤其是对于带宽受限的用户而言。幸运的是,我们可以使用 Effective Type API 来实现它们的带宽较慢,并为它们提供更小的 JPEG。

此接口使用有效往返时间和关闭值来估算用户正在使用的网络类型。它仅返回一个字符串,表示慢速 2G、2G、3G 或 4G。因此,如果用户使用的是 4G 网络以下,我们可以根据该值将视频元素替换为图片。

if (navigator.connection.effectiveType) { ... }

这样做虽然会让用户体验稍有下降,但至少网站在网速较慢时仍可使用。

延迟加载屏幕外图片

轮播界面、滑块或非常长的页面通常会加载图片,即使用户无法立即在网页上看到它们也是如此。

Lighthouse 将在屏幕外图像审核中标记此行为,您也可以在开发者工具的网络面板中自行查看这一行为。如果您看到传入的图片很多,而页面上只有少数图片可见,这意味着您可以考虑延迟加载这些图片。

浏览器本身尚不支持延迟加载,因此我们必须使用 JavaScript 来添加此功能。我们使用了 Lazysizes 库向 Oodle 封面添加延迟加载行为。

<!-- Import library -->
import lazysizes from 'lazysizes'  <!-- or -->
<script src="lazysizes.min.js"></script>

<!-- Use it -->

<img data-src="image.jpg" class="lazyload"/>
<img class="lazyload"
    data-sizes="auto"
    data-src="image2.jpg"
    data-srcset="image1.jpg 300w,
    image2.jpg 600w,
    image3.jpg 900w"/>

Lazysizes 很智能,因为它不仅可以跟踪元素的可见性变化,还可以主动预提取视图附近的元素,以提供最佳用户体验。此外,它还提供 IntersectionObserver 的可选集成,可让您非常高效地进行可见性查询。

完成此更改后,系统会按需提取我们的图片。如果您想更深入地了解该主题,请参阅 images.guide,这是一份非常方便且全面的资源。

帮助浏览器及早提供关键资源

通过网络传送到浏览器的每个字节并非都有相同程度的重要程度,浏览器深知这一点。许多浏览器都采用启发法来确定首先应提取的内容。因此,有时它们会在提取图片或脚本之前提取 CSS。

我们作为网页作者,可以告知浏览器什么对我们真正重要。幸运的是,在过去几年里,浏览器供应商添加了许多功能来帮助我们实现这一点,例如 link rel=preconnectpreloadprefetch资源提示

Web 平台引入的这些功能可帮助浏览器在正确的时间提取正确的内容,与使用脚本实现的一些基于逻辑的自定义加载方法相比,它们可能更高效一些。

我们来看一下 Lighthouse 如何实际指导我们有效使用其中一些功能。

Lighthouse 提醒我们首先要做的就是避免前往任何出发地进行多次成本高昂的往返。

避免往返任何出发地的多次往返行程
图 17.避免往返任何出发地多次往返行程

在 Oodle 应用中,我们实际上大量使用了 Google Fonts。每当您将 Google Font 样式表放入您的网页时,它都会连接最多两个子网域。Lighthouse 告诉我们的意思是,如果我们能够预热该连接,就可以在初始连接时间内节省多达 300 毫秒的时间。

利用链接关联预连接,我们可以有效掩盖连接延迟。

特别是对于像 Google Fonts 这样的工具,我们的字体 CSS 托管在 googleapis.com 上,而我们的字体资源托管在 Gstatic 上,这会产生巨大的影响。因此,我们实施了这一优化,将时间缩短了几百毫秒。

Lighthouse 建议的下一个方法是预加载关键请求。

预加载密钥请求
图 18.预加载密钥请求

<link rel=preload> 的功能非常强大,它会告知浏览器当前导航需要某个资源,并尝试让浏览器尽快提取该资源。

现在,Lighthouse 告诉我们应该预加载主要的网页字体资源,因为我们要以两种网页字体进行加载。

预加载网页字体的操作如下所示:指定 rel=preload,传入包含字体类型的 as,然后指定尝试加载的字体类型,例如 woff2。

这对网页的影响非常显著。

预加载资源的影响
图 19.预加载资源的影响

通常,在不使用 link rel 预加载的情况下,如果网页字体恰巧对您的网页至关重要,浏览器必须首先提取您的 HTML,并解析您的 CSS,之后再获取网页字体。

使用 link rel 预加载,当浏览器解析您的 HTML 后,实际上就可以更早开始提取这些网页字体了。在我们的应用中,这能够缩短使用网页字体渲染文本所需的时间。

如果您打算尝试使用 Google Fonts 预加载字体,那么此过程并不那么简单,但有一个问题。

我们在样式表的字体上指定的 Google Font 网址是字体团队定期更新的网址。这些网址可能会过期或定期更新,因此如果您希望完全控制字体加载体验,我们建议您自行托管网页字体。这种方式非常实用,因为您可以通过它访问链接 rel 预加载等功能。

在本示例中,我们发现 Google Web Fonts Helper 工具非常有助于离线使用其中一些网页字体并进行本地设置,因此请务必查看该工具。

无论您是将网页字体用作关键资源的一部分,还是恰好使用 JavaScript,都请努力帮助浏览器尽快提供您的关键资源。

实验性功能:优先级提示

今天有点特别的事要和你分享。除了资源提示和预加载等功能之外,我们还在开发一项全新的实验性浏览器功能,我们称之为优先级提示。

为最初显示的内容设置优先级
图 20.优先级提示

这是一项新功能,可让您提示浏览器某个资源有多重要。它公开了一种新的属性,即重要性,其值分别为低、高或自动。

这样,我们就可以降低不太重要的资源(例如非关键样式、图片)的优先级,或提取 API 调用以减少争用。我们还可以提高更重要内容(例如主打图片)的优先级。

就我们的 Oodle 应用而言,这实际上带来了一个我们可以进行优化的切入点。

为最初显示的内容设置优先级
图 21.为最初显示的内容设置优先级

在向图片添加延迟加载之前,浏览器执行的操作是,我们拥有包含所有涂鸦的图片轮播界面,并且浏览器在轮播界面最开始提取所有图片,并尽早采用高优先级。遗憾的是,轮播界面中间的图片对用户来说是最重要的。我们所做的是,将这些背景图片的重要性设置为非常低,将前景图片的重要性设置为非常高,这对慢速 3G 造成了两秒的影响,并让我们获取和渲染这些图片的速度有多快。所以这是一次不错的积极体验。

我们希望几周后在 Canary 上推出此功能,敬请留意。

制定网页字体加载策略

排版是良好设计的基础,如果您使用的是网页字体,最好不要阻止文本的渲染,也绝对不希望显示不可见的文本。

我们现在在 Lighthouse 中突出显示了这一点,通过审核,了解避免加载网络字体时的不可见文本

加载网页字体时避免使用不可见文本
图 22.避免在网页字体加载期间显示不可见文本

如果您使用字体块加载网络字体,将让浏览器决定在提取该网络字体需要很长时间的情况下该执行什么操作。有些浏览器会在等待 3 秒钟后回退到系统字体,最终会在下载完字体后将其换成系统字体。

我们力求避免这种不可见的文本,因此在本例中,如果网页字体用时太长,我们将无法查看本周的经典涂鸦。幸运的是,借助一项名为 font-display 的新功能,您实际上可以更好地控制此过程。

    @font-face {
      font-family: 'Montserrat';
      font-style: normal;
      font-display: swap;
      font-weight: 400;
      src: local('Montserrat Regular'), local('Montserrat-Regular'),
          /* Chrome 26+, Opera 23+, Firefox 39+ */
          url('montserrat-v12-latin-regular.woff2') format('woff2'),
            /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
          url('montserrat-v12-latin-regular.woff') format('woff');
    }

字体显示可帮助您根据网络字体的交换时间来决定其呈现或回退的方式。

在本例中,我们将使用字体显示交换。交换为字体指定 0 秒的阻止期,以及无限的交换期。这意味着,如果字体加载需要一段时间,浏览器将会立即使用回退字体绘制文本。字体可用后,它会交换字体。

就我们的应用而言,这样做的好处在于,它可以让我们尽早显示一些有意义的文本,并在准备就绪后过渡到网页字体。

字体显示结果
图 23.字体显示结果

一般来说,如果您恰巧在使用网页字体(大部分网页都在使用网页字体),请制定一个良好的网页字体加载策略。

有许多网络平台功能可用于优化字体加载体验,不过您也可以查看 Zach Leatherman 的 Web Font Recipes 代码库,因为该工具非常棒。

减少阻塞渲染的脚本

我们可以将应用的其他部分推送到下载链的前面部分,以提前至少提供一些基本的用户体验。

在 Lighthouse 时间轴栏上,您可以看到,在前几秒内,所有资源都加载完成后,用户实际上看不到任何内容。

减少阻塞渲染的样式表的机会
图 24.减少阻塞渲染的样式表的机会

下载和处理外部样式表会阻止我们的呈现流程继续进行。

我们可以稍微提前提供一些样式,尝试优化我们的关键渲染路径。

如果我们提取负责这种首次呈现的样式并将其内嵌到 HTML 中,浏览器便能够立即呈现它们,而无需等待外部样式表到达。

在本例中,我们使用名为 重大的 NPM 模块在构建步骤中将关键内容内嵌在 index.html 中。

虽然此模块为我们完成了大部分繁重工作,但要使这个模块在不同的路线中顺利运行,仍然有点棘手。

如果您不够谨慎,或者您的网站结构非常复杂,并且没有从一开始就规划应用 Shell 架构,那么引入此类模式可能会非常困难。

正因如此,尽早考虑性能非常重要。如果从一开始就不针对性能进行设计,以后很可能会遇到问题。

最终,我们的风险回报了,我们设法使其正常运行,应用也更早开始分发内容,从而显著缩短了首次有效渲染时间。

结果

上面列出了大量为网站实施的性能优化措施。我们来看看结果。下图显示了我们的应用在优化前后在中型移动设备上通过 3G 网络进行加载的过程。

Lighthouse 的性能得分从 23 分上升到了 91 分。这在速度方面已经非常可观了所有变化都是在我们持续查看和遵循 Lighthouse 报告推动的。如果您想了解我们如何从技术上实现所有改进,请随时查看我们的代码库,尤其是到达此处的 PR。

预测性性能 - 数据驱动的用户体验

我们相信,在许多领域,机器学习技术都代表着未来的令人振奋的机遇。 我们希望在未来能引发更多实验,那就是真实数据可以真正引导我们打造的用户体验。

如今,我们会做出大量随机决定,决定用户可能想要什么或需要什么,从而决定哪些值得预提取、预加载或缓存。如果我们猜对了,我们可以优先选择少量资源,但很难将资源扩展到整个网站。

我们现在掌握的数据可以更好地用于优化我们的优化措施。 使用 Google Analytics Reporting API,我们可以查看网站上任意网址的下一个热门网页和退出百分比,从而确定应该优先考虑哪些资源。

如果我们将其与良好的概率模型结合使用,就可以避免过度预提取内容而浪费用户数据。我们可以利用 Google Analytics(分析)数据,并使用机器学习和马尔可夫链神经网络等模型来实现此类模型。

适用于 Web 应用的数据驱动型捆绑
图 25.适用于 Web 应用的数据驱动型捆绑方式

为了推动这项实验,我们非常高兴地宣布一项名为 Guess.js 的新计划。

Guess.js
图 26.Guess.js

Guess.js 是一个项目,专注于数据驱动的 Web 用户体验。我们希望能激发人们探索如何使用数据来提升网页性能,并且不止于此。它都是开源的,目前可在 GitHub 上找到。这是由 Minko Gechev、来自 Gatsby 的 Kyle Matthews、Katie Hempenius 和许多其他人与开源社区协作开发的。

请访问 Guess.js,并与我们分享你的想法。

摘要

得分和指标对于提高 Web 速度很有帮助,但它们只是方法,而不是目标本身。

我们都曾在旅途中遇到过网页加载速度缓慢的情况,但现在我们有机会为用户提供加载速度非常快的更愉悦体验。

提升效果是一个过程。大量的小改变可以带来巨大的效果。通过使用合适的优化工具并密切关注 Lighthouse 报告,您可以为用户提供更好、更具包容性的体验。

特别感谢:Ward Peeters、Minko Gechev、Kyle Mathews、Katie Hempenius、Dom Farolino、Yoav Weiss、Susie Lu、Yusuke Utsunomiya、Tom Ankers、Lighthouse 和 Google 涂鸦。