Chrome、Opera 和 Yandex 浏览器中提供的Save-Data 客户端提示请求标头可让开发者向选择在浏览器中启用数据节省模式的用户提供更轻巧、更快速的应用。
对轻量级网页的需求

所有人都认同,网页速度越快、体积越小,用户体验就越好,内容理解和记忆效果就越好,转化次数和收入也就越多。Google 研究表明,“…与原始网页相比,经过优化的网页的加载速度提高了 4 倍,字节用量减少了 80%。由于这类网页的加载速度提高了许多,因此其浏览量也增加了 50%。”
虽然 2G 连接的数量终于开始下降,但 2G 在 2015 年仍然是主流网络技术。3G 和 4G 网络的普及率和可用性正在迅速提高,但对于数亿用户而言,相关的所有权成本和网络限制仍然是一个重要因素。
这些都是支持网页优化的有力论据。
还有其他方法可以提高网站速度,而无需直接涉及开发者,例如代理浏览器和转码服务。虽然此类服务非常受欢迎,但它们也存在一些明显的缺点:图像和文字压缩简单(有时甚至令人无法接受)、无法处理安全 (HTTPS) 网页、仅优化通过搜索结果访问的网页等。这些服务之所以如此受欢迎,本身就表明 Web 开发者未能妥善满足用户对快速轻量型应用和网页的强烈需求。但实现这一目标是一条复杂而有时艰难的道路。
Save-Data 请求标头
一种相当简单直接的方法是借助浏览器,使用 Save-Data 请求标头。通过识别此标头,网页可以为受成本和性能限制的用户自定义并提供优化的用户体验。
受支持的浏览器(如下所示)允许用户启用 *流量节省模式,该模式会授予浏览器应用一组优化措施的权限,以减少渲染网页所需的数据量。当此功能公开或宣传时,浏览器可能会请求较低分辨率的图片、延迟加载某些资源,或通过应用其他特定于内容的优化(例如图片和文本资源压缩)的服务来路由请求。
浏览器支持
- Chrome 49 及更高版本会在用户在移动设备上启用“流量节省程序”选项或在桌面浏览器上启用“流量节省程序”扩展程序时,宣传
Save-Data。 - 当用户在桌面设备上启用“Opera Turbo”模式或在 Android 浏览器上启用“节省流量”选项时,Opera 35 及更高版本会宣传
Save-Data。 - Yandex 16.2 及更高版本会在桌面设备或移动浏览器上启用 Turbo 模式时宣传
Save-Data。
检测 Save-Data 设置
为了确定何时向用户提供“轻量版”体验,您的应用可以检查 Save-Data 客户端提示请求标头。此请求标头表示客户端因传输费用高昂、连接速度缓慢或其他原因而希望减少流量使用。
当用户在浏览器中启用数据节省模式时,浏览器会将 Save-Data 请求标头附加到所有传出请求(包括 HTTP 和 HTTPS)。截至撰写本文时,浏览器仅在标头中宣传一个 *on- 令牌 (Save-Data: on),但未来可能会扩展此功能以指示其他用户偏好设置。
此外,还可以在 JavaScript 中检测 Save-Data 是否已开启:
if ('connection' in navigator) {
if (navigator.connection.saveData === true) {
// Implement data saving operations here.
}
}
检查 navigator 对象中是否存在 connection 对象至关重要,因为该对象表示网络信息 API,而该 API 仅在 Chrome、Chrome(Android 版)和 Samsung Internet 浏览器中实现。这样一来,您只需检查 navigator.connection.saveData 是否等于 true,即可在该条件下实现任何数据保存操作。
如果您的应用使用服务工作线程,则可以检查请求标头并应用相关逻辑来优化体验。或者,服务器可以在 Save-Data 请求标头中查找广告偏好设置,并返回替代响应,例如不同的标记、更小的图片和视频等。
实施提示和最佳实践
- 使用
Save-Data时,请提供一些支持它的界面设备,并允许用户轻松切换体验。例如:- 通知用户
Save-Data受支持,并鼓励他们使用。 - 允许用户通过适当的提示和直观的开启/关闭按钮或复选框来识别和选择模式。
- 选择“节省流量模式”后,宣布并提供一种简单明了的方式来停用该模式,并在需要时恢复到完整体验。
- 通知用户
- 请注意,轻量级应用并非低级应用。它们不会省略重要的功能或数据,只是更清楚地了解所涉及的成本和用户体验。例如:
- 图库应用可能会提供较低分辨率的预览,或者使用代码量较少的轮播机制。
- 搜索应用可能会一次返回较少的结果,限制包含大量媒体内容的结果数量,或减少呈现网页所需的依赖项数量。
- 新闻网站可能会减少显示的新闻报道数量、省略不太受欢迎的类别,或提供较小的媒体预览。
- 提供服务器逻辑以检查
Save-Data请求标头,并考虑在启用该标头时提供替代的更轻量级网页响应,例如减少所需资源和依赖项的数量、应用更积极的资源压缩等。- 如果您要根据
Save-Data标头提供替代响应,请务必将其添加到 Vary 列表 (Vary: Save-Data) 中,以告知上游缓存,只有在存在Save-Data请求标头的情况下,它们才应缓存并提供此版本。如需了解详情,请参阅与缓存互动的最佳实践。
- 如果您要根据
- 如果您使用 Service Worker,则可以通过检查
Save-Data请求标头是否存在或检查navigator.connection.saveData属性的值来检测数据节省选项是否已启用。如果已启用,请考虑是否可以重写请求以提取更少的字节,或使用已提取的响应。 - 考虑使用其他信号来扩充
Save-Data,例如有关用户连接类型和技术的信息(请参阅 NetInfo API)。例如,您可能希望向任何使用 2G 连接的用户提供轻量级体验,即使Save-Data未启用也是如此。反之,用户使用“快速”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 状态,并且可在网页上的任何位置使用。在了解了此机制后,我们来看几个示例,了解如何使用此机制来限制我们向用户发送的数据量。
为高分辨率屏幕提供低分辨率图片
网页上图片的一个常见用例是提供两张一组的图片:一张用于“标准”屏幕 (1x),另一张用于高分辨率屏幕(例如 Retina 显示屏),其大小是前者的两倍 (2x)。这类高分辨率屏幕不一定仅限于高端设备,并且正变得越来越普遍。如果用户偏好更轻量级的应用体验,那么向这些屏幕发送较低分辨率 (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; ?>">
您可以在 CSS 中以 <html> 元素上的 save-data 类为目标,更改图片的传送方式。您可以向高分辨率屏幕发送低分辨率背景图片(如上面的 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 来放弃发送其他非关键资源,例如某些字体。
省略非必要的网页字体
虽然与图片相比,Web 字体通常不会占据给定网页总载荷的很大一部分,但它们仍然非常受欢迎。它们也不会消耗少量数据。此外,浏览器提取和呈现字体的方式比您想象的要复杂得多,其中涉及 FOIT、FOUT 和浏览器启发式方法等概念,使得呈现成为一项细致的操作。
因此,对于想要获得更精简用户体验的用户,您可能需要省略非必需的网络字体。Save-Data 使此操作变得相当轻松。
例如,假设您已在网站上添加了 Google 字体中的 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。