借助 Chrome、Opera 和 Yandex 浏览器中提供的 Save-Data
客户端提示请求标头,开发者可以向在浏览器中选择启用数据节省模式的用户提供更轻量、更快速的应用。
对轻量页面的需求
所有人都同意,网页加载速度越快、体积越小,用户体验就越令人满意,用户对内容的理解和留存率也会越高,进而带来更多转化和收入。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 令牌,但未来可能会扩展此令牌,以指明其他用户偏好设置。
此外,您还可以在 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
,即可在该条件下实现任何数据保存操作。
如果您的应用使用了服务工作器,则可以检查请求标头并应用相关逻辑来优化体验。或者,服务器也可以在 Save-Data
请求标头中查找所宣传的偏好设置,并返回备用响应(不同的标记、较小的图片和视频等)。
实现提示和最佳实践
- 使用
Save-Data
时,请提供一些支持它的界面设备,并允许用户在体验之间轻松切换。例如:- 通知用户支持
Save-Data
,并鼓励他们使用Save-Data
。 - 允许用户通过适当的提示和直观的开启/关闭按钮或复选框来识别和选择模式。
- 选择流量节省模式后,请读出相关信息,并提供一种简单明了的方法来停用该模式,并根据需要恢复为完整体验。
- 通知用户支持
- 请注意,轻量应用并不代表功能较少。他们不会省略重要功能或数据,只是更注重相关成本和用户体验。例如:
- 照片库应用可能会提供分辨率较低的预览,或者使用代码较少的轮播界面机制。
- 搜索应用一次可能返回的结果更少,限制包含大量媒体内容的结果数量,或减少呈现网页所需的依赖项数量。
- 以新闻为主的网站可能会显示较少的报道、省略不太热门的类别,或提供较小的媒体预览。
- 提供服务器逻辑来检查
Save-Data
请求标头,并考虑在启用该标头时提供更轻量级的备用页面响应,例如减少所需资源和依赖项的数量、应用更激进的资源压缩等。- 如果您要根据
Save-Data
标头提供备用响应,请务必将其添加到“Vary”列表 (Vary: Save-Data
),以告知上游缓存,只有在存在Save-Data
请求标头时,它们才应缓存和提供此版本。如需了解详情,请参阅与缓存交互的最佳实践。
- 如果您要根据
- 如果您使用的是服务工件,则应用可以通过检查
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 中,请求标头存储在 $_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
采取行动,以免发送其他非关键资源,例如某些字体。
省略不必要的 Web 字体
虽然网页字体通常占给定网页总载荷的比例远不如图片,但它们仍然很受欢迎。它们也不会消耗大量数据。此外,浏览器提取和呈现字体的操作比您想象的要复杂得多,FOIT、FOUT 和浏览器启发词语等概念使得呈现成为一项细致的操作。
因此,对于希望获得更轻量用户体验的用户,您可能需要舍弃不必要的 Web 字体。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
。