开发什么都能快速加载的网站可能并非易事。大量 以及设备所连接的网络的质量 可能会使这项任务看起来很难。虽然我们可以 如何利用浏览器功能提高加载性能,我们怎么知道 用户设备的网络性能或网络质量 连接?解决之道是 提示!
客户端提示是一组选择启用的 HTTP 请求标头 用户设备及其所连接网络的这些方面。修改者 因此改变了我们的实现方式 根据设备和/或网络条件显示内容。这有助于我们 打造更具包容性的用户体验。
一切都围绕内容协商
客户端提示是另一种内容协商方法,这意味着 基于浏览器请求标头的内容响应。
内容协商的一个例子是
Accept
请求标头。它描述了浏览器能识别的内容类型,
服务器可用来协商响应。对于图片请求,内容
的 Accept
标头为:
Accept: image/webp,image/apng,image/*,*/*;q=0.8
虽然所有浏览器都支持 JPEG、PNG 和 GIF 等图片格式,但接受 在这种情况下,浏览器也支持 WebP 和 APNG。利用这些信息,我们可以 协商每个浏览器的最佳图片类型:
<?php
// Check Accept for an "image/webp" substring.
$webp = stristr($_SERVER["HTTP_ACCEPT"], "image/webp") !== false ? true : false;
// Set the image URL based on the browser's WebP support status.
$imageFile = $webp ? "whats-up.webp" : "whats-up.jpg";
?>
<img src="<?php echo($imageFile); ?>" alt="I'm an image!">
与 Accept
一样,客户端提示是协商内容的另一种途径,但
设备功能和网络条件的背景。有了客户提示,
可以根据用户的个人情况做出服务器端性能决策
例如,决定是否应向服务器提供非关键资源
网络状况不佳的用户在本指南中,我们将介绍
还有一些可用提示,以及有助于提升内容传送效率的一些方法
提供便利
选择启用
与 Accept
标头不同,客户端提示不仅会神奇地出现(使用
Save-Data
除外)。为了确保
您需要选择接收哪些客户端提示
当用户请求发送 Accept-CH
标头时,
资源:
Accept-CH: Viewport-Width, Downlink
Accept-CH
的值是以英文逗号分隔的网站请求提示列表
用于确定后续资源请求的结果。当
客户读取此标头,系统被告知“此网站想要Viewport-Width
和 Downlink
个客户提示。”您无需担心具体提示本身。
我们稍后会解答这些问题。
您可以使用任何后端语言设置这些选择启用标头。例如,PHP 的
可以使用 header
函数。
您甚至可以使用http-equiv
属性
使用 <meta>
标记时:
<meta http-equiv="Accept-CH" content="Viewport-Width, Downlink" />
所有客户端提示!
客户端提示描述了以下两种内容之一:用户所使用的设备、使用以及 他们用来访问您网站的网络我们简单介绍一下 可用提示。
设备提示
一些客户端提示会描述用户设备的特征,通常为屏幕 特征。其中一些资源可以帮助您为客户选择最合适的媒体资源, 但并非所有屏幕都以媒体为中心。
在我们介绍此列表之前,了解一些关键术语,可能会对您有所帮助 描述屏幕和媒体分辨率:
固有尺寸:媒体资源的实际尺寸。例如,如果 当您在 Photoshop 中打开图片时,图片大小对话框中显示的尺寸 描述其固有大小。
经过密度校正的固有尺寸: 已针对像素密度更正了该值。这是图片的固有大小 除以设备像素 比率。 以下面的标记为例:
<img
src="whats-up-1x.png"
srcset="whats-up-2x.png 2x, whats-up-1x.png 1x"
alt="I'm that image you wanted."
/>
假设在本例中 1x
图片的固有尺寸为 320x240,
2x
图片的固有尺寸为 640x480。如果客户端解析此标记
安装在屏幕设备像素比为 2 的设备上(例如,Retina 显示屏)
屏幕),则会请求 2x
图片。密度校正的固有尺寸
2x
图片的尺寸为 320x240,因为 640x480 除以 2 得出的结果是 320x240。
外部尺寸:媒体资源在 CSS 和其他布局之后的尺寸
因素(例如 width
和 height
属性)。让我们
假设您有一个 <img>
元素,用于加载已校正密度的图片
固有尺寸为 320x240,但它也具有 CSS width
和 height
属性
分别应用了 256px
和 192px
值。在此示例中
该 <img>
元素的外部尺寸将变为 256x192。
width: 256px;
的 CSS 规则
和 height: 192px;
转换一个固有大小的 320x240 图片
外部尺寸为 256x192 的广告素材。了解了一些术语之后,我们来看一下设备专用列表 为您提供的客户端提示
视口宽度
Viewport-Width
是用户视口的宽度(以 CSS 像素为单位):
Viewport-Width: 320
此提示可与其他特定于屏幕的提示结合使用,以传达不同的 针对特定屏幕尺寸的最佳图片处理方式(即剪裁) (例如,艺术 方向), 或省略对当前屏幕宽度而言不必要的资源。
DPR
DPR
(设备像素比)的缩写,用于报告物理像素与 CSS 的比率
像素:
DPR: 2
在选择与屏幕的
像素密度(类似于 srcset
中的 x
描述符)
属性)。
宽度
Width
提示出现在由 <img>
或
使用了 sizes
的 <source>
个标记
属性。
sizes
用于告知浏览器资源的外部大小;
Width
使用该外在尺寸来请求具有固有尺寸的图片
是当前布局的最佳选择。
例如,假设用户请求的网页宽度为 320 CSS 像素
DPR 为 2设备加载包含 <img>
元素的文档,该元素包含
sizes
属性值 85vw
(即全部视口宽度的 85%
屏幕尺寸)。如果已选择接受 Width
提示,客户端将发送
此 Width
会通过请求 <img>
的 src
来提示服务器:
Width: 544
在这种情况下,客户端会提示服务器, 所请求图片的宽度将为视口宽度的 85%(272 像素) 乘以屏幕的 DPR (2),即 544 像素。
这一提示尤为有力,因为它不仅考虑了 屏幕的密度校正宽度,但也与这一关键部分 以及图片在布局内的外在尺寸信息。如此一来, 服务器就有机会协商对这两者都最优的图片响应 屏幕和布局。
内容-DPR
虽然您已经知道屏幕具有设备像素比,但资源也
都有各自的像素比在最简单的资源选择用例中,
设备和资源之间的宽高比可以相同。但是!如果
DPR
和 Width
头文件,则资源的外部大小可以
会产生出现差异的场景。这就是 Content-DPR
提示的地方
。
与其他客户端提示不同,Content-DPR
不是供以下 API 使用的 request 标头
而是响应标头服务器必须发送响应DPR
和
Width
提示用于选择资源。Content-DPR
的值应
是以下等式的结果:
Content-DPR
= [所选图片资源大小] / ([Width
] / [DPR
])
发送 Content-DPR
请求标头后,浏览器就会知道如何扩缩
屏幕的设备像素比和布局的指定图像。如果没有它,
图片可能无法正确缩放。
设备内存
从技术层面来讲,这是设备内存的组成部分
API 中,Device-Memory
会显示
您实际使用的
记忆
当前设备的存储空间大小(以 GiB 为单位):
Device-Memory: 2
此提示的一个可能用例是,减少 JavaScript 代码量, 可发送给内存有限的设备上的浏览器,因为 JavaScript 是最常 会占用大量资源的内容类型的浏览器 加载。 或者,您可以发送更低的 DPR 图像,因为它们使用的解码内存更少。
网络提示
Network Information API 提供了另一种 描述用户网络性能的客户端提示类别 连接。在我看来,这些是最有用的提示集。有了它们,我们 通过改变我们提供服务的方式,为用户量身打造体验 在慢速连接上向客户端传递资源
RTT
RTT
提示提供大致的往返时间(以毫秒为单位),
应用层与传输层 RTT 不同,RTT
提示包含
服务器处理时间。
RTT: 125
此提示很有用,因为延迟在加载性能方面发挥着重要作用。
使用 RTT
提示,我们可以根据网络响应能力做出决策,
这有助于加快完整体验的交付(例如,
省略某些请求)。
下行链路
虽然延迟时间对加载性能很重要,但带宽也有影响
。Downlink
提示(以兆比特每秒 (Mbps) 表示)可揭示
用户连接的大致下行速度:
Downlink: 2.5
与 RTT
结合使用时,Downlink
在改变内容显示方式方面非常有用
根据网络连接质量向用户提供
厄瓜多尔时间
ECT
提示代表“Effective Connection Type”。其值是
连接类型的枚举列表,其中每个连接都描述了
在 RTT
和 Downlink
的指定范围内
值。
此标头没有说明实际的连接类型是什么,具体如下:
它不会报告您的网关是手机基站还是 Wi-Fi 访问
。而是分析当前连接的延迟时间和带宽,
确定它最相似的网络配置文件。例如,如果您连接到
通过 Wi-Fi 连接到慢速网络,ECT
可能会填充值 2g
,
该值是最接近有效连接的近似值:
ECT: 2g
ECT
的有效值包括 4g
、3g
、2g
和 slow-2g
。此提示可以是
用作评估连接质量的起点,随后
使用 RTT
和 Downlink
提示进行优化。
保存数据
Save-Data
并不是描述网络状况的提示,而是用户
偏好设置,说明网页应发送较少的数据。
我更喜欢将 Save-Data
分类为网络提示,因为许多事情
这与其他网络提示类似。用户还可能会
可能在高延迟/低带宽环境中启用此功能。这个提示
始终显示如下:
Save-Data: on
在 Google,我们已经讨论了
Save-Data
。
它对性能的影响可能非常深远。它是一种信号
真的会要求你少给他们发送一些东西!如果你认真倾听并采取相应行动
用户会喜欢它。
融会贯通
使用客户端提示执行的操作取决于您。因为它们提供 您有多种选择。为了让您产生灵感,让我们看看 客户提示对小康有何帮助 木材,一种虚构的木材 这家公司位于中西部农村地区。远程工作通常如此 区域, 因此网络连接变得很脆弱这时客户端等技术就会提示 能够为用户带来真正的改变
自适应图片
除了最简单的自适应图片用例之外,其他所有用例都可能会很复杂。如果你
同一图片针对不同屏幕采用多种处理方式和变体
尺寸和格式?该标记会变得非常复杂
快速。
人很容易犯错,也容易忘记或误解重要信息
概念(例如 sizes
)。
虽然 <picture>
和 srcset
不可否认很棒,但它们
为复杂的用例开发和维护耗时。我们可以实现自动化
但生成标记也很困难
<picture>
和 srcset
提供的功能非常复杂,满足他们的自动化需求
保持其灵活性
客户端提示可以简化这一过程。与客户端协商图片响应 提示可能如下所示:
- 如果适用于您的工作流程,请先选择图片处理方式(即
艺术类图像)时,请查看
Viewport-Width
提示。 - 通过检查
Width
提示和DPR
提示来选择图片分辨率,并且 选择适合图片的布局尺寸和屏幕密度的来源(类似 了解x
和w
描述符在srcset
中的工作原理)。 - 选择浏览器支持的最佳文件格式(
Accept
可以帮助我们在大多数浏览器中完成相应操作)。
在我虚构的木材公司客户方面,我开发了一个 使用客户端提示的 PHP 中的自适应图片选择例程。这意味着 而不是将此标记发送给所有用户:
<picture>
<source
srcset="
company-photo-256w.webp 256w,
company-photo-512w.webp 512w,
company-photo-768w.webp 768w,
company-photo-1024w.webp 1024w,
company-photo-1280w.webp 1280w
"
type="image/webp"
/>
<img
srcset="
company-photo-256w.jpg 256w,
company-photo-512w.jpg 512w,
company-photo-768w.jpg 768w,
company-photo-1024w.jpg 1024w,
company-photo-1280w.jpg 1280w
"
src="company-photo-256w.jpg"
sizes="(min-width: 560px) 251px, 88.43vw"
alt="The Sconnie Timber Staff!"
/>
</picture>
我能够根据各个浏览器的支持情况,将其简化为以下形式:
<img
src="/image/sizes:true/company-photo.jpg"
sizes="(min-width: 560px) 251px, 88.43vw"
alt="SAY CHEESY PICKLES."
/>
在此示例中,/image
网址是一个带参数的 PHP 脚本
改写者
mod_rewrite。它
它采用图片文件名和其他参数来帮助后端脚本
在指定条件下选择最佳图片。
我感觉“但这不只是重新实现了 <picture>
和 srcset
,
”是您的第一个问题。
从某种意义上说是的,但有一个重要的区别:当应用使用 客户提示撰写媒体响应时,大部分(如果不是全部)工作 其中可能包括可执行该操作的服务(例如 CDN) 。而使用 HTML 解决方案,则需要将新的标记写入 能够满足各种应用场景的需要当然,您可以自动生成标记。如果您的 但很有可能您就需要 并回顾您的自动化策略。
客户端提示让您可以使用无损的高分辨率图像开始,
然后可动态调整其大小,从而针对任意组合实现最佳效果
屏幕和布局与 srcset
不同,它要求您枚举固定的
可供浏览器选择的可能候选图片的列表,此方法
可能更加灵活虽然 srcset
会强制您为浏览器提供粗略的
(例如,256w
、512w
、768w
和 1024w
)- client-hints
赋能的解决方案可适应所有宽度,而无需大量标记。
当然,您无需自行编写图片选择逻辑。Cloudinary
使用 w_auto
时,使用客户端提示来创建图片响应
参数,
并观察到,使用浏览器时,中位数用户下载的字节数减少了 42%
辅助性客户端提示。
但要注意!桌面版 Chrome 67 中的一些变化不再支持 适用于跨域客户端 提示。 幸运的是,这些限制不会影响移动版 Chrome,并且 针对功能进行升级后,所有平台都会全面升级 Policy。
为网速较慢的用户提供帮助
自适应性能的理念是,我们可以调整资源的分发方式, 根据客户端提示提供给我们的信息生成;具体来说就是 有关用户网络连接的当前状态的信息。
对于 Sconnie Timber 的网站,我们采取了一些措施来减轻
网络速度较慢,Save-Data
、ECT
、RTT
和 Downlink
标头使用
检查过哪些漏洞完成后,我们会生成一个网络质量报告,
得分,我们据此确定是否应干预,以获得更好的用户
体验。此网络得分介于 0
到 1
之间,其中 0
为最低
网络质量,1
是最佳。
最初,我们检查 Save-Data
是否存在。如果是,则得分将设置为
0
,因为我们假设用户希望我们执行使
让应用变得更轻巧、更快速
不过,如果 Save-Data
不存在,我们会继续计算 ECT
的值,
RTT
和 Downlink
提示计算描述网络的得分
连接质量。网络得分生成来源
代码
可在 GitHub 上找到。结论是,如果我们在实验中使用与网络相关的提示,
一些时尚,我们可以为网速慢的用户提供更好的体验
。
![与不使用客户端的网站进行比较
提示应适应慢速网络连接(左图),
(右)。](https://web.developers.google.cn/static/articles/performance-optimizing-content-efficiency-client-hints/image/a-comparison-a-site-doe-b20caac28fc7f.png?authuser=8&hl=uk)
当网站根据客户端提示提供的信息进行调整时,我们就不必采用 “一刀切”式的方法。我们可以智能地确定要 send。我们可以修改自适应图片选择逻辑, 以便在网络质量不佳时提高性能, 很差。
在此示例中,我们可以看到客户端提示对 改善网站在网速较慢时的性能。以下是一个 WebPagetest 无法根据客户端提示进行调整的网站广告瀑布流:
![史康尼河的 WebPagetest 瀑布
木材网站在网速较慢时加载所有资源。](https://web.developers.google.cn/static/articles/performance-optimizing-content-efficiency-client-hints/image/a-webpagetest-waterfall-6bc17bbfd8c27.png?authuser=8&hl=uk)
现在,同一网站在慢速连接上呈现的 瀑布图, 之后,该网站会使用客户端提示排除非关键网页资源:
![史康尼河的 WebPagetest 瀑布
使用客户端提示来决定不在某个位置加载非关键资源的木材网站
网络连接速度太慢](https://web.developers.google.cn/static/articles/performance-optimizing-content-efficiency-client-hints/image/a-webpagetest-waterfall-3ba4268e712f2.png?authuser=8&hl=uk)
客户端提示将网页加载时间从 45 秒以上缩短到不到 10%。在这种情况下,客户提示的优势 能够得到足够强调,对寻求关键信息的用户来说 通过慢速网络传输信息。
此外,您还可以使用客户端提示而不破坏游戏体验
。例如,如果我们要调整
遵循 ECT
提示的值,同时仍然提供完整的
则我们可以将回退到默认值
如下所示:
// Set the ECT value to "4g" by default.
$ect = isset($_SERVER["HTTP_ECT"]) ? $_SERVER["HTTP_ECT"] : "4g";
其中,"4g"
表示 ECT
标头中质量最高的网络连接
描述。如果我们将 $ect
初始化为 "4g"
,不支持客户端的浏览器就会停止响应
提示不会受到影响。选择加入 FTW!
小心缓存!
每当您根据 HTTP 标头更改响应时,都需要注意
缓存将如何处理以后对该资源的提取。Vary
标头为
在这里是不可或缺的,因为它将缓存条目缓存到请求标头的值
。简而言之,如果您根据指定的 HTTP 请求修改任何响应,
请求标头,您几乎应始终在 Vary
中包含该标头
如下所示:
Vary: DPR, Width
但有一点需要特别注意:切勿对可缓存内容执行 Vary
操作。
在频繁更改的标题(如 Cookie
)上发送响应,因为这些
导致资源实际上无法缓存。知道这一点后,您可能希望
对 RTT
或 Downlink
等客户端提示标头执行 Vary
操作,因为这些是
可能频繁变化的连接因素。如果您想修改
则可以考虑仅输入 ECT
标头,
最大限度地减少缓存未命中。
当然,这仅适用于您首先缓存响应的情况。
例如,如果 HTML 资源的内容是动态的,您就不需要缓存这些资源,因为
可能会对重复访问的用户体验造成不利影响。遇到这类情况时,请
您可随时根据需要修改此类回答,
Vary
。
Service Worker 中的客户端提示
内容协商已不再局限于服务器!由于 Service Worker
作为客户端和服务器之间的代理,您可以控制
通过 JavaScript 投放。这包括客户端提示。在 Service Worker 中
fetch
事件,可以使用 event
对象的
request.headers.get
方法读取资源的请求标头,如下所示:
self.addEventListener('fetch', (event) => {
let dpr = event.request.headers.get('DPR');
let viewportWidth = event.request.headers.get('Viewport-Width');
let width = event.request.headers.get('Width');
event.respondWith(
(async function () {
// Do what you will with these hints!
})(),
);
});
您选择的任何客户端提示标头都可以以这种方式进行读取。尽管如此,
这并不是获取其中部分信息的唯一途径。针对特定广告网络的提示
可在 navigator
对象中的以下等效 JavaScript 属性中读取:
客户端提示 | JS 等效项 |
---|---|
ECT | `navigator.connection.effectiveType` |
RTT | `navigator.connection.rtt` |
“保存数据” | `navigator.connection.saveData` |
`Downlink` | `navigator.connection.downlink` |
“设备内存” | `navigator.deviceMemory` |
由于这些 API 并不适用于所有位置,因此您需要向
in
运算符:
if ('connection' in navigator) {
// Work with netinfo API properties in JavaScript!
}
在这里,您可以使用与在服务器上使用的逻辑类似的逻辑,但以下情况除外: 您不需要服务器来与客户端提示协商内容。服务 单靠劳动者就能够打造更快、更有弹性的体验, 增添了在用户离线时提供内容的功能。
总结
有了客户端提示,我们就能够为所在区域的用户提供更快的体验
完全渐进式的方式我们可以根据用户的设备投放媒体
因此,您可以更轻松地提供自适应图片,
适用于 <picture>
和 srcset
,尤其是对于复杂的用例。这使我们能够
这不仅可以减少开发方面的时间和精力,还可以优化
使资源(尤其是图片)能够定位到用户所用屏幕
进行得比
或许更重要的是,我们可以探出连接不良的网络连接状况, 通过修改我们发送的内容及其发送方式来减少用户的差距。这可以 在帮助脆弱网络用户更轻松地访问网站方面发挥着长远的作用。 通过与 Service Worker 结合使用,我们可以打造出 可离线使用
客户端提示仅适用于 Chrome 和基于 Chromium 那么您就可以以不妨碍浏览的方式使用它们 。不妨考虑使用客户端提示 提供包容且适应性强的体验,能够感知每位用户的设备 功能及其所连接的网络。希望其他浏览器供应商 会看到它们的价值,并表现出实施的意愿。
资源
感谢 Ilya Grigorik 和 Eric Portis、Jeff Posnick、Yoav Weiss 和 Estelle Weyl, 请针对本文提供宝贵的反馈和修改。