我以 50 MB 的预算使用了一天的网络

已发表: 2022-03-10
快速总结 ↬数据可能非常昂贵,尤其是在发展中国家。 Chris Ashton 设身处地为数据预算紧张的人着想,并提供了一些实用技巧来减少我们网站的数据占用空间。

这篇文章是我尝试在各种限制下使用网络的系列文章的一部分,代表给定的用户群体。 我希望提高真实人们面临的困难的形象,如果我们以一种同情他们需求的方式进行设计和开发,这些困难是可以避免的。

上次,我使用 Internet Explorer 8 浏览了一天的网页。这次,我以 50 MB 的预算浏览了一天的网页。

为什么是 50 MB?

我们中的许多人都很幸运能够使用每月允许数 GB 数据传输的移动计划。 如果做不到这一点,我们通常能够连接到高速宽带连接上的家庭或公共 WiFi 网络,并且有效地拥有无限数据。

但在世界上有些地方,移动数据非常昂贵,而且宽带基础设施很少或根本没有。

人们通常一次只购买数十兆字节的数据包,这使得千兆字节成为相对较大且因此购买昂贵的数据量。
——Cable.co.uk 的消费电信分析师 Dan Howdle

我们说的到底有多贵?

跳跃后更多! 继续往下看↓

移动数据的成本

cable.co.uk 2018 年的一项研究发现,津巴布韦是世界上移动数据成本最高的国家,1 GB 的平均成本为 75.20 美元,从 12.50 美元到 138.46 美元不等。 价格的巨大范围是由于少量数据非常昂贵,您承诺的数据计划越大,价格就越便宜。 您可以阅读研究方法以获取更多信息。

津巴布韦绝不是一次性的。 赤道几内亚、圣赫勒拿和福克兰群岛紧随其后,1 GB 的数据成本分别为 65.83 美元、55.47 美元和 47.39 美元。 这些国家/地区的技术基础设施通常较差,采用率较低,这意味着数据的交付成本很高,而且没有规模经济来降低成本。

欧洲部分地区的数据也很昂贵。 希腊一千兆字节的数据将花费您 32.71 美元; 在瑞士,20.22 美元。 相比之下,相同数量的数据在英国的成本为 6.66 美元,在美国为 12.37 美元。 另一方面,印度是世界上数据最便宜的地方,平均成本为 0.26 美元。 吉尔吉斯斯坦、哈萨克斯坦和乌克兰紧随其后,分别为每 GB 0.27 美元、0.49 美元和 0.51 美元。

移动网络的速度也因国家而异。 也许令人惊讶的是,在全球至少 30 个国家,包括澳大利亚和法国,用户通过移动网络体验到比 WiFi 更快的速度。 韩国的移动下载速度最快,平均为 52.4 Mbps,但伊拉克最慢,平均下载速度为 1.6 Mbps,上传速度为 0.7 Mbps。 美国在移动下载速度方面排名世界第 40 位,约为 34 Mbps,随着世界向 5G 迈进,美国有进一步落后的风险。

在移动网络连接类型方面,英国 84.7% 的用户连接使用 4G,而美国为 93%,韩国为 97.5%。 相比之下,乌兹别克斯坦不到 50%,阿尔及利亚、厄瓜多尔、尼泊尔和伊拉克不到 60%。

宽带数据的成本

与此同时,一项对 2018 年宽带成本的研究表明,尼日尔的宽带连接“每月每兆比特”成本为 263 美元。 这个指标有点难以理解,所以举个例子:如果一个国家宽带套餐的平均成本是 22 美元,而套餐提供的平均下载速度是 10 Mbps,那么“每月每兆比特”的成本将是为 2.20 美元。

这是一个有趣的指标,承认宽带速度与数据上限一样重要。 263 美元的成本表明宽带速度极慢且成本极高。 作为参考,该指标在英国为 1.19 美元,在美国为 1.26 美元。

也许更容易理解的是宽带套餐的平均成本。 请注意,这项研究正在寻找最便宜的宽带套餐,忽略这些套餐是否有数据上限,因此提供了一个有用的大致数字,而不是数据本身的成本。

仅就套餐成本而言,毛里塔尼亚拥有世界上最昂贵的宽带,平均为 768.16 美元(范围为 307.26 美元至 1,368.72 美元)。 这笔巨大的成本包括为该物业建造物理线路,因为毛里塔尼亚已经很少有线路了。 毛里塔尼亚的宽带网络速度为 0.7 Mbps,也是世界上最慢的宽带网络之一。

台湾拥有世界上最快的宽带,平均速度为 85 Mbps。 也门的速度最慢,为 0.38 Mbps。 但即使是拥有完善的宽带基础设施的国家也有所谓的“非热点”。 英国的宽带速度在 207 个国家中排名第 34 位,但 2019 年 7 月,英国仍有一所学校没有宽带。

英国宽带套餐的平均成本为 39.58 美元,美国为 67.69 美元。 世界上最便宜的平均价格是乌克兰的,仅为 5 美元,尽管其中最便宜的宽带交易是在吉尔吉斯斯坦(1.27 美元,而全国平均水平为 108.22 美元)。

津巴布韦是移动数据成本最高的国家,其宽带数据也好不到哪里去,平均成本为 128.71 美元,“每月每兆位”成本为 6.89 美元。

绝对成本与实际成本

根据研究时的汇率,到目前为止列出的所有成本都是以美元计的绝对成本。 这些成本尚未计入生活成本,这意味着对于许多国家而言,实际成本实际上要高得多。

我将今天的浏览限制为 50 MB,在津巴布韦,移动数据资费约为 3.67 美元。 这听起来可能不多,但津巴布韦的教师今年正在罢工,因为他们的工资已降至每天 2.50 美元。

相比之下,3.67 美元大约是美国最低工资 7.25 美元的一半。 作为津巴布韦人,我必须工作大约一天半才能赚到钱来购买这 50MB 的数据,而在美国只需半小时。 比较国家之间的生活成本并不容易,但仅就工资而言,津巴布韦 50 MB 数据的 3.67 美元成本对于美国人来说就像最低工资标准的 52 美元。

设置实验

我启动了 Chrome 并打开了开发工具,在那里我将网络限制为缓慢的 3G 连接。 我想模拟乌兹别克斯坦用户体验的那种慢速连接,看看网站会给我什么样的体验。 我还限制了我的 CPU 以模拟在低端设备上。

我选择将我的网络限制为慢 3G,并将我的 CPU 限制为 6 倍。 (大预览)

我安装了 ModHeader 并设置了“Save-Data”标题,让网站知道我想尽量减少数据使用量。 这也是 Chrome 为 Android 的“精简模式”设置的标头,我将在稍后详细介绍。

我下载了 TripMode; 适用于 Mac 的应用程序,可让您控制 Mac 上的哪些应用程序可以访问互联网。 任何其他应用程序的 Internet 访问都会被自动阻止。

跳闸模式设置截图; Chrome 已启用,邮件已禁用
您可以使用 TripMode 启用/禁用单个应用程序连接到 Internet。 我启用了 Chrome。 (大预览)

我预测我的 50 MB 预算能走多远? 一个网页的平均重量接近 1.7 MB,这表明我的预算中大约有 29 个页面,但如果我能够留在相同的站点并利用浏览器缓存,可能会比这更多。

在整个实验过程中,我将提出一些性能提示,以加快页面的第一次内容绘制和感知加载时间。 其中一些技巧可能不会影响直接传输的数据量,但通常会延迟下载不太重要的资源,这在慢速连接时可能意味着永远不会下载资源并保存数据。

本实验

事不宜迟,我加载了 google.com,使用了 402 KB 的预算并花费了 0.03 美元(大约是我津巴布韦预算的 1%)。

传输 402 KB,1.1 MB 资源,24 个请求
传输 402 KB,1.1 MB 资源,24 个请求。 (大预览)

总而言之,页面大小不错,但我想知道这 24 个网络请求来自哪里,以及页面是否可以变得更轻。

谷歌主页——DOM

DOM 的 Chrome devtools 屏幕截图,我在其中扩展了一个内联style标记。 (大预览)

查看页面标记,没有外部样式表——所有的 CSS 都是内联的。

性能提示 #1:内联关键 CSS

这对性能有好处,因为它节省了浏览器必须发出额外的网络请求才能获取外部样式表,因此可以解析样式并立即应用于第一个内容绘制。 这里需要权衡取舍,因为外部样式表可以被缓存,但内联样式表不能(除非你对 JavaScript 很聪明)。

一般的建议是你的关键样式(任何首屏样式)是内联的,你的其余样式是外部的并异步加载。 CSS 的异步加载可以通过一行非常巧妙的 HTML 来实现:

 <link rel="stylesheet" href="/path/to/my.css" media="print" onload="this.media='all'">

devtools 显示了 DOM 的美化版本。 如果您想查看实际下载到浏览器的内容,请切换到 Sources 选项卡并找到该文档。

缩小的代码墙。
切换到 Sources 并找到索引会显示传递给浏览器的“原始”HTML。 真是一团糟! (大预览)

你可以看到这里有很多内联 JavaScript。 值得注意的是,它已经被丑化了,而不仅仅是缩小了。

性能提示 #2:缩小和丑化您的资产

缩小删除了不必要的空格和字符,但丑化实际上“破坏”了代码更短。 明显的迹象是代码包含简短的、机器生成的变量名,而不是未经修改的源代码。 这很好,因为这意味着脚本更小,下载速度更快。

即便如此,内联脚本看起来大约是 210 KB 页面资源的 120 KB(大约是 60 KB gzip 大小的一半)。 此外,在下载的 402 KB 中,还有 5 个外部 JavaScript 文件,总计 291 KB:

显示外部 javascript 文件的 DevTools 的网络选项卡
devtools 的 Network 选项卡中的五个外部 JavaScript 文件。 (大预览)

这意味着 JavaScript 约占整个页面重量的 80%。

这不是无用的 JavaScript; 谷歌必须有一些才能在您输入时显示建议。 但我怀疑其中很多是跟踪代码和广告设置。

为了比较,我禁用了 JavaScript 并重新加载了页面:

DevTools 仅显示 5 个网络请求
禁用的 JS 版本的 Google 搜索只有 102 KB,只有 5 个网络请求。 (大预览)

禁用 JS 的 Google 搜索版本只有 102 KB,而不是 402 KB。 尽管 Google 无法在这些情况下提供自动建议,但该网站仍然可以正常运行,而且我刚刚将数据使用量减少到原来的四分之一。 如果我真的不得不长期限制我的数据使用量,我要做的第一件事就是禁用 JavaScript。 它并不像听起来那么糟糕。

性能提示 #3:少即是多

内联、丑化和缩小资产都很好,但最好的性能来自于一开始就不发送资产。

  • 在添加任何新功能之前,您是否制定了性能预算?
  • 在将 JavaScript 添加到您的站点之前,您的功能是否可以使用纯 HTML 来完成? (例如,HTML5 表单验证)。
  • 在将大型 JavaScript 或 CSS 库拉入您的应用程序之前,请使用类似 bundlephobia.com 之类的工具来衡量它的大小。 便利值得重量吗? 你能用更小数据量的普通代码完成同样的事情吗?

分析资源信息

这里有很多东西要解压,所以让我们开始吧。 我只有 50 MB 的空间可以玩,所以我要挤满这个页面加载的每一点。 接受简短的 Chrome Devtools 教程。

传输了 402 KB,但传输了 1.1 MB 资源:这实际上意味着什么?

这意味着实际下载了 402 KB 的内容,但是以压缩形式(使用 gzip 或 brotli 等压缩算法)。 然后浏览器必须做一些工作才能将其解压缩成有意义的东西。 解压缩数据的总大小为 1.1 MB。

这种解包不是免费的——解压资源需要几毫秒的开销。 但与发送 1.1MB 的数据相比,这只是微不足道的开销。

性能提示 #4:压缩基于文本的资源

作为一般规则,请始终使用 gzip 之类的方式压缩您的资产。 但是不要对你的图像和其他二进制文件使用压缩——你应该提前在源代码上优化它们。 压缩实际上最终会使它们变大。

并且,如果可以,请避免压缩 1500 字节或更小的文件。 最小的 TCP 数据包大小为 1500 字节,因此通过压缩到 800 字节,您什么也没有保存,因为它仍然在同一个字节数据包中传输。 同样,成本可以忽略不计,但浪费了服务器上的一些压缩 CPU 时间和客户端上的解压缩 CPU 时间。

现在回到 Chrome 中的“网络”选项卡:让我们深入研究这些优先事项。 请注意,资源的优先级从“最高”到“最低”——这些是浏览器对要下载的更重要资源的最佳猜测。 优先级越高,浏览器越早尝试下载资产。

性能提示 #5:向浏览器提供资源提示

浏览器会猜测最高优先级的资产是什么,但您可以使用<link rel="preload">标签提供资源提示,指示浏览器尽快下载资产。 预加载字体、徽标和其他任何出现在首屏的内容是个好主意。

让我们谈谈缓存。 我将按住 ALT 并右键单击以更改列标题以解锁更多有趣的信息。 我们将检查 Cache-Control。

显示如何显示缓存控制信息的屏幕截图
ALT 后面隐藏着许多有趣的领域。 (大预览)

Cache-Control 表示是否可以缓存资源,可以缓存多长时间,以及在重新验证时应该遵循哪些规则。 设置适当的缓存值对于降低重复访问的数据成本至关重要。

性能提示 #6:在所有可缓存资产上设置缓存控制标头

请注意,缓存控制值以publicprivate指令开头,后跟过期值(例如max-age=31536000 )。 该指令是什么意思,为什么会有奇怪的特定max-age值?

显示缓存控制列的 Google 网络选项卡的屏幕截图
最大年龄值和公共/私人的混合。 (大预览)

31536000是一年中的秒数,是缓存控制规范允许的理论最大值。 通常会看到此值应用于所有静态资产,并且实际上意味着“此资源不会改变”。 实际上,没有浏览器会缓存一整年,但只要有意义,它就会缓存资产。

为了解释 public/private 指令,我们必须解释存在于服务器之外的两个主要缓存。 首先,有传统的浏览器缓存,其中资源存储在用户的机器(“客户端”)上。 然后是位于客户端和服务器之间的 CDN 缓存; 资源被缓存在 CDN 级别,以防止 CDN 一遍又一遍地向源服务器请求资源。

显示缓存如何与服务器交互的图表
资源。 (大预览)

publicCache-Control指令允许将资源缓存在客户端和 CDN 中。 private值意味着只有客户端可以缓存它; CDN 不应该这样做。 后一个值通常用于身份验证后存在的页面或资产,可以将其缓存在客户端上,但我们不希望通过将其缓存在 CDN 中并将其传递给其他用户来泄漏私人信息。

Google logo cache-control 设置截图:private, max-age=31536000
最大年龄值和公共/私人的混合。 (大预览)

引起我注意的一件事是 Google 徽标具有“私人”的缓存控制。 页面上的其他图像确实有公共缓存,我不知道为什么会以不同方式处理徽标。 如果您有任何想法,请在评论中告诉我!

我刷新了页面,大部分资源都是从缓存中提供的,除了页面本身,正如你已经看到的那样,它是private, max-age=0 ,这意味着它不能被缓存。 这对于动态网页来说是正常的,在这些网页中,用户在刷新时始终获得最新的页面很重要。

正是在这一点上,我不小心点击了 devtools 中的“说明”URL,这将我带到了网络分析参考,花费了我大约 5 MB 的预算。 哎呀。

谷歌开发文档

这个新的 5 MB 页面中有 4.2 MB 用于图像; 特别是 SVG。 其中最重的是 186 KB,这并不是特别大——它们太多了,而且它们都是一次下载的。

向下滚动很长的开发文档页面的 Gif
这是一个很长的页面。 页面加载时下载的所有图像。 (大预览)

5 MB 的页面加载量是我今天预算的 10%。 到目前为止,我已经使用了 5.5 MB,包括 Google 主页的无 JavaScript 重新加载,并且花费了 0.40 美元。 我什至没有打开这个页面的意思。

这里有什么更好的用户体验?

性能提示 #7:延迟加载图像

通常,如果我不小心点击了一个链接,我会点击浏览器中的后退按钮。 下载这些图像对我没有任何好处——浪费了 4.2 MB!

除了视频,您通常知道自己在做什么,图像是迄今为止网络上数据使用的最大罪魁祸首。 一项对世界 500 强网站的研究发现,图片占据了平均页面重量的 53%。 “这意味着它们对页面加载时间和随后的整体性能有很大影响”。

与其在页面加载时下载所有图像,不如延迟加载图像,以便只有与页面互动的用户支付下载它们的费用。 因此,选择不在首屏下方滚动的用户不会浪费任何不必要的带宽下载他们永远不会看到的图像。

有一个很棒的 css-tricks.com 指南,用于为图像推出延迟加载,它在连接良好的图像、连接不良的图像和禁用 JavaScript 的图像之间提供了良好的平衡。

如果此页面按照上面的指南实现了延迟加载,则默认情况下,38 个 SVG 中的每一个都将由 1 KB 占位符图像表示,并且仅在滚动时加载到视图中。

性能提示 #8:为您的图像使用正确的格式

我认为谷歌没有使用 WebP,这是一种图像格式,它的大小比 PNG 小 26%(质量没有损失),比 JPEG 小 25-34%(以及质量相当)。 我想我会尝试将 SVG 转换为 WebP。

转换为 WebP 确实使其中一个 SVG 从 186 KB 减少到仅 65 KB,但实际上,并排查看图像时,WebP 出现颗粒状:

两张图片的比较
SVG(左)明显比 WebP(右)清晰。 (大预览)

然后我尝试将其中一个 PNG 转换为 WebP,它应该是无损的,并且应该更小。 然而,WebP 输出*重*(127 KB,从 109 KB)!

两张图片的比较
PNG(左)与 WebP(右)的质量相似,但比 127 KB 更小,为 109 KB。 (大预览)

这让我很惊讶。 WebP 不一定是我们认为的灵丹妙药,甚至 Google 也忽略了在此页面上使用它。

所以我的建议是:在可能的情况下,在每个图像的基础上尝试不同的图像格式。 以最小尺寸保持最佳质量的格式可能不是您期望的格式。

现在回到 DOM。 我遇到了这个:

代码截图
(大预览)

注意到 Google 分析脚本上的async关键字了吗?

devtools 性能分析输出截图
谷歌分析具有“低”优先级。 (大预览)

尽管这是文档开头的第一件事,但它的优先级很低,因为我们已经通过使用async关键字明确选择不成为阻塞请求。

阻塞请求是停止页面呈现的请求。 <script>调用默认是阻塞的,在脚本下载、编译和执行之前停止 HTML 的解析。 这就是我们传统上将<script>调用放在文档末尾的原因。

性能提示 #9:避免编写阻塞脚本调用

通过将async属性添加到我们的<script>标记,我们告诉浏览器不要停止呈现页面,而是在后台下载脚本。 如果在下载脚本时 HTML 仍在解析中,则在执行脚本时暂停解析​​,然后恢复。 这比在遇到<script>时立即阻止渲染要好得多。

还有一个defer属性,略有不同。 <script defer>告诉浏览器在后台加载脚本时渲染页面,即使在下载脚本时 HTML 仍在解析中,脚本也必须等到页面渲染完成后才能执行. 这使得脚本完全非阻塞。 阅读“使用延迟和异步高效加载 JavaScript”以获取更多信息。

无论如何,足够的谷歌剖析。 是时候尝试另一个网站了。 我的预算还剩将近 45 MB!

亚马逊

亚马逊主页截图
(大预览)

亚马逊主页加载的总重量约为 6 MB。 其中之一是我什至在页面上找不到的 587 KB 图像。 这是一个PNG,大概有清晰的文本,但在摄影背景上——一个经典的组合,对性能来说很糟糕。

带有重叠文本的扳手图像:动手时间。发现我们为您的汽车选择的工具
这个颗粒状的图像使用了我预算的 1% 以上。 (大预览)

事实上,在我的网络选项卡中有几个几百 KB 的图像,我在页面上实际上是看不到的。 我怀疑亚马逊某处的配置错误,但这些不可见的图像结合在一起至少吞噬了我的 1 MB 数据。

英雄形象呢? 它是页面上的主图像,仅传输了 94 KB - 但如果直接在文本和足球运动员周围裁剪,它的大小可能会减少约 15%。 然后我们可以在 CSS 中应用与图像中相同的背景颜色。 这具有额外的优势,即可以调整到更小的屏幕,同时保持文本的易读性。

屏幕截图显示:英超联赛 - 直播 Prime 视频
(大预览)

我已经说过一次,我会再说一遍:优化和延迟加载您的图像是您可以为网站的页面权重带来的最大好处

到目前为止,优化图像提供了最显着的数据减少。 你可以证明 JavaScript 对整体性能的影响更大,但对数据减少没有影响。 优化或删除图像是确保更轻松体验的最安全方式,也是流量节省程序所依赖的主要优化方式。
— Tim Kadlec,了解 Chrome Lite 页面

公平地说,如果我将浏览器调整为移动设备大小并刷新页面,则该网站针对移动设备进行了优化,总页面重量仅为 2.1 MB。

101 个请求,已传输 2.1 MB
101 个请求,传输了 2.1 MB。 (大预览)

但这让我想到了下一点……

性能提示 #10:不要对数据连接做出假设

很难检测桌面上的某人是否正在使用宽带连接,或者是否正在通过数据受限的加密狗或移动设备进行网络共享。 很多人就是这样在火车上工作,或者生活在宽带基础设施较差但移动信号强的地区。 在亚马逊的案例中,在桌面网站上可以节省一些大数据,我们不应该仅仅因为屏幕尺寸表明我不在移动设备上而自满。

是的,如果我们的视口是“桌面大小”,我们应该期待更大的页面加载,因为与颗粒状的移动图像相比,图像会更大,并且针对屏幕进行了更好的优化。 但是页面不应该大几个数量级。

此外,我在请求中发送了Save-Data标头。 此标头明确表示倾向于减少数据使用,我希望将来有更多网站开始注意到它。

最初的“桌面”负载可能为 6 MB,但在观看了一分钟后,随着较低优先级的资源和事件跟​​踪开始起作用,它已攀升至 8.6 MB。 此页面重量包括近 1.7 MB 的缩小 JavaScript。 我什至不想开始看那个。

性能提示 #11:为您的 JavaScript 使用 Web Workers

哪个会更糟——1.7 MB 的 JavaScript 或 1.7 MB 的图像? 答案是 JavaScript:这两种资产在性能方面并不等同。

JPEG 图像需要在屏幕上进行解码、光栅化和绘制。 需要下载 JavaScript 包,然后对其进行解析、编译、执行——引擎还需要完成许多其他步骤。 请注意,这些成本并不完全相等。
— Addy Osmani, 2018 年 JavaScript 的成本

如果您必须发布这么多 JavaScript,请尝试将其放入 web worker 中。 这使大部分 JavaScript 远离主线程,现在可以释放主线程来重新绘制 UI,帮助您的网页在低功率设备上保持响应。

我现在的预算大约有 15.5 MB,并且已经花费了津巴布韦数据预算中的 1.14 美元。 我必须要当老师半天才能挣到钱才能走到这一步。

Pinterest

我听说 Pinterest 的表现不错,所以我决定对其进行测试。

惊人的 327 个请求,产生了 6.1 MB 的数据。
惊人的 327 个请求,产生了 6.1 MB 的数据。 (大预览)

也许这不是最公平的测试; 我被带到了登录页面,在该页面上,一个异步过程发现我已登录 Facebook 并自动登录。 页面加载相对较快,但随着越来越多的内容被预加载,请求逐渐增加。

然而,我看到在随后的页面加载中,Service Worker 显示了大部分内容——节省了大约一半的页面重量:

8.2 / 15.6 MB 资源,以及由服务工作者缓存处理的 39 / 180 个请求。
8.2 / 15.6 MB 资源,以及由服务工作者缓存处理的 39 / 180 个请求。 (大预览)

Pinterest 网站是一个渐进式网络应用程序; 它安装了一个服务工作者来手动处理 CSS 和 JS 的缓存。 我现在可以关闭我的 WiFi 并继续使用该网站(尽管不是很有用):

加载微调器和消息说:你没有连接到互联网
离线时您无能为力。 (大预览)

性能提示 #12:使用 Service Worker 提供离线支持

如果我只需要通过网络加载一次网站,现在即使我离线也可以获得我需要的所有信息,那不是很好吗?

一个很好的例子是显示本周天气预报的网站。 我应该只需要下载该页面一次。 如果我关闭我的移动数据并随后在某个时候返回该页面,它应该能够为我提供最后已知的内容。 如果我再次连接到 Internet 并加载页面,我将获得更新的预测,但 CSS 和图像等静态资产仍应由 service worker 在本地提供。

这可以通过设置具有良好缓存策略的服务工作者来实现,以便可以离线重新访问缓存的页面。 lodash 文档网站是野外服务工作者的一个很好的例子:

在每个请求旁边显示“ServiceWorker”的 devtools 屏幕截图
Lodash 文档离线工作。 (大预览)

很少更新并且很可能经常使用的内容是服务人员治疗的完美候选者。 具有不断变化的新闻提要的动态站点不太适合离线体验,但仍然可以从中受益。

Pinterest 上 Chris Ashton 个人资料的屏幕截图
第二个 Pinterest 页面加载为 443 KB。 (大预览)

当您的数据预算紧张时,服务人员可以真正为您节省一天的时间。 我不相信 Pinterest 体验在数据使用方面是最佳的——即使在只有少量图像的页面上,后续页面也约为 0.5 MB 标记——但让你的 JavaScript 为你处理页面请求并保持相同的导航元素到位可以非常高效。 对于可通过单页应用程序呈现的文章的回访,BBC 管理的传输大小仅为 3.1 KB。

到目前为止,仅 Pinterest 就已经消耗了 14 MB,这意味着我已经花掉了大约 30 MB 的预算,或者津巴布韦预算的 2.20 美元(几乎是一天的工资)。

我最好小心我最后的 20 MB……但那有什么乐趣呢?

游戏点

我之所以选择这个,是因为过去在我的手机上感觉明显迟缓,我想深入了解原因。 果然,加载主页会消耗 8.5 MB 的数据。

主页旁边的 devtools 屏幕截图
Gamespot 主页流量高达 8.5 MB,请求数量高达 347 个。 (大预览)

其中 6.5 MB 是页面中间的一个自动播放视频,公平地说,直到我开始滚动时才开始下载。 尽管如此…

我的视口中的视频的 Gif 屏幕截图
视频被剪辑到屏幕外。 (大预览)

我只能在视口中看到一半的视频——右侧被剪掉了。 它也是 30 秒长,我敢打赌大多数人不会坐下来观看整件事。 这一单一资产使页面大小增加了两倍多。

性能提示 #13:不要预加载视频

通常,除非您网站的主要通信方式是视频,否则不要预加载它。

如果您是 YouTube 或 Netflix,可以合理地假设访问您页面的人希望视频自动加载和自动播放。 人们期望视频会咀嚼一些数据,但这是对内容的公平交换。 但是,如果您是一个主要媒体是文本和图像的网站——而你恰好提供了额外的视频内容——那么不要预加载视频。

想想带有嵌入视频的新闻文章。 许多用户只想浏览文章标题,然后再继续下一步。 其他人将阅读该文章,但忽略任何嵌入。 其他人会努力点击并观看每个嵌入的视频。 我们不应该假设他们想要观看这些视频而占用每个用户的带宽。

重申:用户不喜欢自动播放视频。 作为开发人员,我们这样做只是因为我们的经理告诉我们这样做,而他们之所以告诉我们这样做只是因为所有最酷的应用程序都在这样做,而最酷的应用程序这样做只是因为视频广告产生的收入是传统广告的 20 到 50 倍广告。 谷歌浏览器已开始根据个人喜好阻止某些网站的自动播放视频,因此即使您将网站开发为自动播放视频,也不能保证您的用户会获得这种体验。

如果我们同意让视频成为一种选择加入体验(点击播放)是个好主意,我们可以更进一步,让它也点击加载。 这意味着使用播放按钮模拟视频占位符图像,并且仅在单击播放按钮时下载视频。 使用快速连接的人应该注意到缓冲速度没有差异,使用慢速连接的人会欣赏您网站的其余部分加载速度有多快,因为它不必预加载大型视频文件。

Anyway, back to Gamespot, where I was indeed forced to preload a large video file I ended up not watching. I then clicked through to a game review page that weighed another 8.5 MB, this time with 5.4 MB of video, before I even started scrolling down the page.

What was really galling was when I looked at what the video actually was. It was an advert for a Samsung TV! This advert cost me $0.40 of my Zimbabwe wages. Not only was it pre-loaded, but it also didn't end up playing anywhere as far as I'm aware, so I never actually saw it.

Screenshot of the offending request
This advert wasted 5.4 MB of my precious data. (大预览)

The 'real' video — the gameplay footage (in other words, the content) — wasn't actually loaded until I clicked on it. And that ploughed through my remaining data in seconds.

而已。 That's my 50 MB gone. I'll need to work another 1.5 days as a Zimbabwean schoolteacher to repeat the experience.

Performance Tip #14: Optimize For First Page Load

What's striking is that I used 50 MB of data and in most cases, I only visited one or two pages on any given site. If you think about it, this is true of most user journeys today.

Think about the last time you Googled something. You no doubt clicked on the first search result. If you got your answer, you closed the tab, or else you hit the back button and moved onto the next search result.

With the exception of a few so-called 'destination sites' such as Facebook or YouTube, where users habitually go as a starting point for other activities, the majority of user journeys are ephemeral. We stumble across random sites to get the answers to our questions, never to return to those sites again.

Web development practices are heavily skewed towards optimising for repeat visitors. “Cache these assets — they'll come in handy later”. “Pre-load this onward journey, in case the user clicks to read more”. “Subscribe to our mailing list”.

Instead, I believe we should optimize heavily for one-off visitors. Call it a controversial opinion, but maybe caching isn't really all that important. How important can a cached resource that never gets surfaced again be ? And perhaps users aren't actually going to subscribe to your mailing list after reading just the one article, so downloading the JavaScript and CSS for the mail subscription modal is both a waste of data and an annoying user experience.

The Decline Of Proxy Browsers

I had hoped to try out Opera Mini as part of this experiment. Opera Mini is a mobile web browser which proxies web pages through Opera's compression servers. It accounts for 1.42% of global traffic as of June 2019, according to caniuse.com.

Opera Mini claims to save up to 90% of data by doing some pretty intensive transcoding. HTML is parsed, images are compressed, styling is applied, and a certain amount of JavaScript is executed on Opera's servers. The server doesn't respond with HTML as you might expect — it actually transcodes the data into Opera Binary Markup Language (OBML), which is progressively loaded by Opera Mini on the device. It renders what is essentially an interactive 'snapshot' of the web page — think of it as a PDF with hyperlinks inside it. Read Tiffany Brown's excellent article, “Opera Mini and JavaScript” for a technical deep-dive.

It would have been a perfect way to eek my 50 MB budget as far as possible. Unfortunately, Opera Mini is no longer available on iOS in the UK. Attempting to visit it in the app store throws an error:

The item you've requested is not currently available in the UK Store.
(大预览)

It's still available “in some markets” but reading between the lines, Opera will be phasing out Opera Mini for its new app — Opera Touch — which doesn't have any data-saving functionality apart from the ability to natively block ads.

Opera desktop used to have a 'Turbo mode', acting as a traditional proxy server (returning a HTML document instead of OBML), applying data-saving techniques but less intensively than Opera Mini. According to Opera, JavaScript continues to work and “you get all the videos, photos and text that you normally would, but you eat up less data and load pages faster”. However, Opera quietly removed Turbo mode in v60 earlier this year, and Opera Touch doesn't have a Turbo mode either. Turbo mode is currently only available on Opera for Android.

Android is where all the action is in terms of data-saving technology. Chrome offers a 'Lite mode' on its mobile browser for Android, which is not available for iPhones or iPads because of “platform constraints“. Outside of mobile, Google used to provide a 'Data Saver' extension for Chrome desktop, but this was canned in April.

Lite mode for Chrome Android can be forcibly enabled, or automatically kicks in when the network's effective connection type is 2G or worse, or when Chrome estimates the page will take more than 5 seconds to reach first contentful paint. Under these conditions, Chrome will request the lite version of the HTTPS URL as cached by Google's servers, and display this stripped-down version inside the user's browser, alongside a “Lite” marker in the address bar.

Screenshot showing button in toolbar denoting 'Lite' mode
'Lite mode' on Chrome for Android. Image: Google. (大预览)

I'd love to try it out — apparently it disables scripts, replaces images with placeholders, prevents loading of non-critical resources and shows offline copies of pages if one is available on the device. This saves up to 60% of data. However, it isn't available in private (Incognito) mode, which hints at some of the privacy concerns surrounding proxy browsers.

Lite 模式与 Google 共享 HTTPS URL,因此这种模式在 Incognito 中不可用是有道理的。 然而,根据 ghacks.net 的说法,cookie、登录信息和个性化页面内容等其他信息不会与谷歌共享,并且“永远不会破坏 Chrome 和网站之间的安全连接”。 有人想知道为什么在 iOS 上似乎不允许使用这些数据保存服务(并且没有关于 Lite 模式是否会在 iOS 上可用的消息)。

数据保护代理需要高度信任; 您的浏览活动、cookie 和其他敏感信息被委托给某些服务器,通常位于另一个国家/地区。 许多代理根本不再工作,因为很多网站已经转向 HTTPS,这意味着 Turbo 模式等举措在很大程度上已成为“无用功能”。 HTTPS 阻止了这种中间人行为,这是一件好事,尽管它意味着其中一些代理服务的消亡,并使那些连接不良的网站更难访问。

我找不到任何 OSX 或 iOS 兼容的数据保存工具,除了 Bandwidth Hero for Firefox(它需要设置您自己的数据压缩服务——远远超出大多数用户的技术能力!)和 skyZIP 代理(最后更新于2017 年充满了错别字,我无法让自己相信)。

结论

减少网站的数据足迹与提高前端性能齐头并进。 这是您可以做的最可靠的事情来加速您的网站。

除了数据成本之外,还有很多充分的理由关注性能,正如 GOV.UK 关于该主题的博客文章所述:

  • 如果加载时间超过 3 秒,53% 的用户会放弃移动网站。
  • 尝试使用慢速连接在网站上完成简单任务时,人们必须多集中 50% 的注意力。
  • 性能更高的网页更能延长用户设备的电池寿命,并且通常需要更少的服务器电源来提供服务。 高性能站点对环境有益。

我们无权改变数据不平等的全球成本。 但我们确实有能力减轻它的影响,改善过程中每个人的体验。