利用 Save-Data 交付快速的轻量级应用

Dave Gash
Dave Gash
Ilya Grigorik
Ilya Grigorik

Chrome、Opera 和 Yandex 浏览器中提供的Save-Data客户端提示请求标头可让开发者向在浏览器中选择启用流量节省模式的用户提供更精简、更快速的应用。

对轻量级页面的需求

Weblight 统计信息

大家都同意,更快、更轻量的网页能提供更令人满意的用户体验,让用户更好地理解和留存内容,并增加转化次数和收入。Google 研究表明,“...经过优化的网页加载速度比原始网页快 4 倍,字节用量减少了 80%。由于这类网页的加载速度提高了许多,因此它们的流量也增加了 50%。”

此外,虽然 2G 连接数最终在下降,但 2015 年,2G 仍占据主导地位的网络技术。3G 和 4G 网络的普及率和可用性正在迅速增长,但相关的拥有成本和网络限制仍然是数亿用户的一个重要因素。

这些都是有助于实现网页优化的有力理由。

您还可以通过其他方法提高网站速度,而无需开发者直接参与,例如使用代理浏览器和转码服务。虽然此类服务非常受欢迎,但它们存在很大的缺陷,包括简单的图片和文本压缩(有时是不可接受的)、无法处理安全 (HTTPS) 网页、仅优化通过搜索结果访问的网页等。这些服务非常受欢迎,这本身表明 Web 开发者没有妥善解决用户对快速、轻量级应用和页面的高需求。但要达到这个目标 并非易事 有时难以抉择

Save-Data 请求标头

一种非常简单的方法是使用 Save-Data 请求标头让浏览器提供帮助。通过识别此标头,网页可以为受费用和性能受限的用户自定义并提供优化的用户体验。

受支持的浏览器(见下文)允许用户启用 *流量节省模式,该模式会授权浏览器应用一系列优化,以减少呈现网页所需的数据流量。当提供或通告此功能时,浏览器可能会请求较低分辨率的图片、延迟加载某些资源,或通过应用了其他内容专用优化(例如图片和文本资源压缩)的服务路由请求。

浏览器支持

  • 当用户在移动设备上启用“流量节省程序”选项或在桌面浏览器上启用“流量节省程序”扩展程序时,Chrome 49 及更高版本会通告 Save-Data
  • 当用户在桌面设备上启用“Opera 加速”模式或在 Android 浏览器上启用“省流量”选项时,Opera 35 及更高版本会播发 Save-Data
  • 在桌面或移动浏览器上启用增强型模式时,Yandex 16.2 及更高版本会通告 Save-Data

检测 Save-Data 设置

为了确定何时为用户提供“轻微”体验,应用可以检查 Save-Data 客户端提示请求标头。此请求标头表明由于传输费用高、连接速度缓慢或其他原因,客户端倾向于降低流量消耗。

当用户在浏览器中启用流量节省模式时,浏览器会将 Save-Data 请求标头附加到所有传出请求(HTTP 和 HTTPS)。截止到撰写本文时,浏览器仅会在标头 (Save-Data: on) 中通告一个 *on- 令牌,但该令牌将来可能会扩展,以指明其他用户偏好设置。

此外,还可以检测 Save-Data 是否已在 JavaScript 中开启:

if ('connection' in navigator) {
  if (navigator.connection.saveData === true) {
    // Implement data saving operations here.
  }
}

检查 navigator 对象中是否存在 connection 对象至关重要,因为它表示 Network Information API,该 API 仅在 Chrome、Chrome(Android 版)和 Samsung Internet 浏览器中实现。然后,您只需检查 navigator.connection.saveData 是否等于 true,即可在该条件下实现任何数据保存操作。

图中所示为 Chrome 开发者工具中的 Save-Data 标头以及流量节省程序扩展程序。
在 Chrome 桌面版中启用流量节省程序扩展程序。

如果您的应用使用 Service Worker,则可以检查请求标头并应用相关逻辑来优化体验。或者,服务器可以在 Save-Data 请求标头中查找通告的偏好设置并返回备用响应,例如不同的标记、较小的图片和视频等。

植入提示和最佳做法

  1. 使用 Save-Data 时,请提供一些支持它的界面设备,并让用户能够轻松切换不同体验。例如:
    • 通知用户Save-Data受支持,并鼓励他们使用。
    • 允许用户通过适当的提示和直观的开/关按钮或复选框来识别和选择模式。
    • 选择流量节省模式后,应予以公布,并提供一种简单而明显的方式来停用该模式,并根据需要还原为完整的体验。
  2. 请记住,轻量级应用不是更小的应用。它们不会遗漏重要的功能或数据,只是更了解相关的费用和用户体验。例如:
    • 图库应用可能会提供分辨率较低的预览,或者使用代码编写量较少的轮播机制。
    • 搜索应用每次返回的结果数可能较少,限制媒体密集型结果的数量,或减少呈现网页所需的依赖项数量。
    • 面向新闻的网站可能会显示较少的报道、省略不太热门的类别,或提供较小的媒体预览。
  3. 提供服务器逻辑以检查是否存在 Save-Data 请求标头,并考虑在启用后提供更轻量的备用页面响应,例如减少所需的资源和依赖项数量、应用更积极的资源压缩等。
    • 如果您要根据 Save-Data 标头提供备用响应,请务必将其添加到 Vary 列表 (Vary: Save-Data) 中,以告知上游缓存仅在存在 Save-Data 请求标头时应缓存并提供此版本。如需了解详情,请参阅与缓存交互的最佳实践。
  4. 如果您使用 Service Worker,则应用可以通过检查是否存在 Save-Data 请求标头或检查 navigator.connection.saveData 属性的值来检测数据保存选项的启用时间。如果启用,请考虑是否可以重写请求以提取较少的字节,或使用已提取的响应。
  5. 考虑使用其他信号来增强 Save-Data,例如有关用户的连接类型和技术的信息(请参阅 NetInfo API)。例如,即使未启用 Save-Data,您也可能需要为使用 2G 连接的任何用户提供轻量级体验。相反,仅仅因为用户使用的是“快速”4G 连接,并不意味着他们对节省流量不感兴趣(例如在漫游时)。此外,您可以使用 Device-Memory 客户端提示来增强 Save-Data 的存在,以进一步适应内存有限的设备用户。用户设备内存也会在 navigator.deviceMemory 客户端提示中通告。

测试方案

通过 Save-Data 能实现的目的仅限于您能想到的内容。为了让您了解可能出现的情况,我们来看几个用例。在阅读本文时,您可能会想出自己的其他用例,因此请大胆试验,看看能获得怎样的可能!

检查服务器端代码中的 Save-Data

虽然您可以在 JavaScript 中通过 navigator.connection.saveData 属性检测 Save-Data 状态,但有时最好在服务器端进行检测。JavaScript 在某些情况下可能无法执行。此外,服务器端检测是在将标记发送到客户端之前修改标记的唯一方式,Save-Data 的一些最有利的用例就涉及到了这一操作。

在服务器端代码中检测 Save-Data 标头的具体语法取决于所使用的语言,但基本思想对于所有应用后端都是相同的。例如,在 PHP 中,请求标头存储在以 HTTP_ 开头的索引处的 $_SERVER 超全局数组中。这意味着您可以通过检查 $_SERVER["HTTP_SAVE_DATA"] 变量是否存在及其值来检测 Save-Data 标头,如下所示:

// false by default.
$saveData = false;

// Check if the `Save-Data` header exists and is set to a value of "on".
if (isset($_SERVER["HTTP_SAVE_DATA"]) && strtolower($_SERVER["HTTP_SAVE_DATA"]) === "on") {
  // `Save-Data` detected!
  $saveData = true;
}

如果您在向客户端发送任何标记之前放置此检查,则 $saveData 变量将包含 Save-Data 状态,并且将可用于网页上的任何位置。通过对这种机制进行说明,我们来看几个示例,说明如何使用它来限制向用户发送的数据量。

为高分辨率屏幕提供低分辨率图片

在 Web 上,图片的常见用例是将图片分成两组提供:一张用于“标准”屏幕 (1x),另一张适用于高分辨率屏幕(例如,Retina 显示屏)。这类高分辨率屏幕不一定仅限于高端设备,而且越来越常见。如果倾向于使用更轻量的应用体验,则明智的做法是向这些屏幕发送较低分辨率 (1x) 的图片,而不是向这些屏幕发送较大 (2x) 的图片。为了在 Save-Data 标头存在时实现这一点,我们只需修改发送到客户端的标记:

if ($saveData === true) {
  // Send a low-resolution version of the image for clients specifying `Save-Data`.
  ?><img src="butterfly-1x.jpg" alt="A butterfly perched on a flower."><?php
}
else {
  // Send the usual assets for everyone else.
  ?><img src="butterfly-1x.jpg" srcset="butterfly-2x.jpg 2x, butterfly-1x.jpg 1x" alt="A butterfly perched on a flower."><?php
}

这个用例完美体现了只需花费很少的精力,就能满足那些特别要求您向其发送较少数据的用户。如果您不喜欢在后端修改标记,也可以通过使用网址重写模块(例如 Apache 的 mod_rewrite)来实现相同的结果。您可以参考一些示例来说明如何通过相对较少的配置实现这一目标

此外,您只需向 <html> 元素添加一个类,即可将这一概念扩展到 CSS background-image 属性:

<html class="<?php if ($saveData === true): ?>save-data<?php endif; ?>">

在这里,您可以将 save-data 类定位到 CSS 中的 <html> 元素,以更改图片的传送方式。您可以将低分辨率的背景图片发送到高分辨率屏幕(如上面的 HTML 示例所示),或者完全省略某些资源。

忽略非必要的图像

网络上的某些图片内容根本就不是必需内容。虽然此类图像可以起到锦上添花的作用,但那些尝试从按流量计费的数据流量套餐中用尽其可能性的人可能并不希望看到它们。在 Save-Data 的最简单的用例中,我们可以使用前面的 PHP 检测代码,并完全省略不必要的图片标记:

<p>This paragraph is essential content. The image below may be humorous, but it's not critical to the content.</p>
<?php
if ($saveData === false) {
  // Only send this image if `Save-Data` hasn't been detected.
  ?><img src="meme.jpg" alt="One does not simply consume data."><?php
}

这种方法肯定会产生明显的效果,如下图所示:

比较缺少 Save-Data 时加载的非关键图像与显示 Save-Data 时忽略同一图像的情况。
比较的是没有 Save-Data 时加载的非关键图像与存在 Save-Data 时加载的非关键图像的情况。

当然,省略图片并不是唯一的可能性。您还可以针对 Save-Data 执行操作,放弃发送其他非关键资源,例如某些字体。

省略非必需的网页字体

虽然网页字体在给定网页的总载荷中所占的比例通常不如图片通常那样,但它们仍然很受欢迎。它们也不会消耗大量数据。此外,浏览器提取和渲染字体的方式比您想象的还要复杂,因为 FOITFOUT 和浏览器启发法等概念使得渲染操作变得细微。

因此,对于想要更精简用户体验的用户,您可能需要保留非必需的网页字体,这无疑是合理的。Save-Data 使此操作变得相当轻松。

例如,假设您在网站上添加了 Google Fonts 中的 Fira Sans。Fira Sans 是一个非常棒的正文字体,但对于想要保存数据的用户来说,它可能并不是那么重要。通过在存在 Save-Data 标头时向 <html> 元素添加 save-data 类,我们可以编写一开始会调用非基本字体的样式,但当 Save-Data 标头出现时,我们将停用该类:

/* Opt into web fonts by default. */
p,
li {
  font-family: 'Fira Sans', 'Arial', sans-serif;
}

/* Opt out of web fonts if the `save-Data` class is present. */
.save-data p,
.save-data li {
  font-family: 'Arial', sans-serif;
}

使用此方法,您可以保留 Google Fonts 中的 <link> 代码段,因为浏览器会通过先向 DOM 应用样式,然后检查是否有任何 HTML 元素调用样式表中的任何资源来推测加载 CSS 资源(包括网页字体)。如果 Save-Data 处于开启状态,用户就永远不会加载 Fira Sans,因为设置了样式的 DOM 从未调用过它。而 Arial 则会开始发挥作用。它没有 Fira Sans 那么好,但对于那些尝试延长流量计划的用户来说,它可能更合适。

摘要

Save-Data 标头没有太多细微差别;它可以开启或关闭,无论原因如何,应用都要根据其设置提供适当的体验。

例如,有些用户怀疑应用内容或功能会丢失,即使在连接状况不佳的情况下,也可能会不允许使用流量节省模式。反过来,有些用户理所当然地可能会启用此功能,使页面尽可能小巧、简洁,即使在良好连接情况下也是如此。最好让您的应用假定用户想要获得完整且无限的体验,直到您通过显式用户操作明确指出这一点。

作为网站所有者和 Web 开发者,我们要负责管理内容,为那些受限于数据流量和费用的用户改善用户体验。

如需详细了解 Save-Data 和出色的实际示例,请参阅帮助用户 Save Data