利用 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 Turbo”模式或在 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 桌面版中启用流量节省程序扩展程序。

如果您的应用使用了服务工作器,则可以检查请求标头并应用相关逻辑来优化体验。或者,服务器也可以在 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

虽然您可以通过 navigator.connection.saveData 属性在 JavaScript 中检测 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),另一张图像的大小是前者的两倍(2x),适用于高分辨率屏幕(例如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)来实现相同的结果。您可以参阅有关如何实现此目的的示例,只需进行少量配置即可。

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

<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 采取行动,以免发送其他非关键资源,例如某些字体。

省略不必要的 Web 字体

虽然网页字体通常占给定网页总载荷的比例远不如图片,但它们仍然很受欢迎。它们也不会消耗大量数据。此外,浏览器提取和渲染字体的方式比您想象的还要复杂,因为 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 资源(包括 Web 字体)。如果 Save-Data 处于开启状态,用户就永远不会加载 Fira Sans,因为设置了样式的 DOM 从未调用过它。系统会改用 Arial。它不如 Fira Sans 好看,但对于那些想延长流量套餐有效期的用户来说,它可能更合适。

摘要

Save-Data 标头没有太多细微之处;它要么处于开启状态,要么处于关闭状态,无论原因如何,应用都必须根据其设置提供适当的体验。

例如,如果部分用户怀疑数据流量保存模式会导致应用内容或功能丢失,即使在网络连接不佳的情况下,他们也可能不会允许启用此模式。相反,有些用户可能会出于常规考虑启用该功能,以尽可能缩减网页大小并使其尽可能简单,即使在网络连接良好的情况下也是如此。最好让您的应用假定用户想要获得完整且无限的体验,直到您通过显式用户操作明确指出这一点。

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

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