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+ 会通告
Save-Data。
检测 Save-Data 设置
为了确定何时向用户提供“轻量”体验,您的应用可以检查 Save-Data 客户端提示请求标头。此请求标头表示客户端希望减少数据用量,原因可能是传输费用高、网速慢或其他原因。
当用户在其浏览器中启用流量节省模式时,浏览器会将 Save-Data 请求标头附加到所有传出请求(HTTP 和 HTTPS)。在撰写本文时,浏览器仅在标头 (Save-Data: on) 中通告一个 *on- 令牌,但未来可能会扩展此令牌,以指示其他用户偏好设置。
此外,您还可以检测是否在 JavaScript 中启用了 Save-Data:
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,并在此条件下实现任何数据保存操作。
如果您的应用使用 Service Worker,则可以检查请求标头并应用相关逻辑来优化体验。或者,服务器可以在 Save-Data 请求标头中查找通告的偏好设置,并返回替代响应,例如不同的标记、较小的图片和视频等。
实现技巧和最佳实践
- 使用
Save-Data时,请提供一些支持该功能的界面设备,并允许用户在不同体验之间轻松切换。例如:- 通知用户
Save-Data受支持,并鼓励他们使用。 - 允许用户通过适当的提示和直观的开/关按钮或复选框来识别和选择模式。
- 选择流量节省模式后,请进行通知,并提供一种简单而明显的方法来停用该模式,以便在需要时恢复完整体验。
- 通知用户
- 请记住,轻量级应用并非低端应用。它们不会省略重要的功能或数据,只是更注重所涉及的成本和用户体验。例如:
- 照片库应用可能会提供分辨率较低的预览,或使用代码量较少的轮播机制。
- 搜索应用可能会一次返回较少的结果、限制媒体密集型结果的数量,或减少呈现网页所需的依赖项数量。
- 新闻类网站可能会显示较少报道、省略不太热门的类别或提供较小的媒体预览。
- 提供服务器逻辑来检查
Save-Data请求标头,并考虑在启用该标头时提供替代的、更轻量的网页响应,例如减少所需资源和依赖项的数量、应用更积极的资源压缩等。- 如果您要根据
Save-Data标头提供备用响应,请务必将其添加到 Vary 列表 (Vary: Save-Data),以告知上游缓存,只有在存在Save-Data请求标头时,它们才应缓存并提供此版本。如需了解详情,请参阅与缓存交互的最佳实践。
- 如果您要根据
- 如果您使用 Service Worker,您的应用可以通过检查是否存在
Save-Data请求标头或检查navigator.connection.saveData属性的值来检测何时启用了流量节省选项。如果已启用,请考虑是否可以重写请求以提取更少的字节,或使用已提取的响应。 - 考虑使用其他信号(例如有关用户连接类型和技术的信息,请参阅 NetInfo API)来增强
Save-Data。例如,您可能希望向使用 2G 连接的任何用户提供轻量级体验,即使未启用Save-Data也是如此。相反,用户使用“快速”4G 连接并不意味着他们对节省流量不感兴趣,例如在漫游时。此外,您还可以使用Device-Memory客户端提示来增强Save-Data的存在感,以便进一步适应内存有限的设备上的用户。用户设备内存也会在navigator.deviceMemory客户端提示中通告。
食谱
您可以通过 Save-Data 实现的目标仅受限于您的想象力。为了让您了解其功能,我们来看几个应用场景。在阅读本文时,您可能会想到自己的其他应用场景,因此请随时进行实验,看看有哪些可能!
在服务器端代码中检查 Save-Data
虽然您可以在 JavaScript 中通过 navigator.connection.saveData 属性检测 Save-Data 状态,但有时最好在服务器端检测。在某些情况下,JavaScript 可能无法执行。此外,服务器端检测是在将标记发送到客户端之前对其进行修改的唯一方法,这涉及 Save-Data 的一些最有利的使用场景。
用于在服务器端代码中检测 Save-Data 标头的具体语法取决于所使用的语言,但对于任何应用后端,基本思路应该都是相同的。例如,在 PHP 中,请求标头存储在 $_SERVER 超全局数组中,索引以 HTTP_ 开头。这意味着,您可以通过检查 $_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; ?>">
在这里,您可以在 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 执行操作,以放弃发送其他非关键资源,例如某些字体。
省略非必要的网页字体
虽然网页字体通常不会像图片那样占据给定网页总载荷的很大一部分,但它们仍然非常受欢迎。它们消耗的数据量也不容小觑。 此外,浏览器提取和呈现字体的方式比您想象的要复杂得多,其中涉及 FOIT、FOUT 和浏览器启发法等概念,这使得呈现操作变得细致入微。
因此,对于希望获得更精简用户体验的用户,您可能需要排除非必要的网页字体。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> 代码段,因为浏览器会推测加载 CSS 资源(包括网页字体),方法是先将样式应用于 DOM,然后检查是否有任何 HTML 元素调用了样式表中的任何资源。如果有人恰好启用了 Save-Data,则 Fira Sans 永远不会加载,因为样式化 DOM 永远不会调用它。而是会使用 Arial。它不如 Fira Sans 那么美观,但对于那些想要节省流量套餐的用户来说,它可能更受欢迎。
摘要
Save-Data 标头没有太多细微差别;它要么处于开启状态,要么处于关闭状态,无论出于何种原因,应用都必须根据其设置提供适当的体验。
例如,如果用户怀疑会丢失应用内容或功能,即使在网络连接不佳的情况下,也可能不允许使用流量节省模式。相反,有些用户可能会自然而然地启用该功能,以便尽可能让网页保持小巧简单,即使在网络连接良好的情况下也是如此。 您的应用最好假定用户希望获得完整且不受限制的体验,除非用户通过明确的操作另有表示。
作为网站所有者和 Web 开发者,我们有责任管理好自己的内容,为流量和费用受限的用户改善用户体验。
如需详细了解 Save-Data 和出色的实际示例,请参阅帮助用户Save Data。