Speculation Rules 是 Google 最近一年新推出的浏览器 API,可以通过预加载和预渲染的方式显著加快单页应用和多页应用的路由或跳转效率。通过在 Web App 中使用 Speculation Rules API,我们可以大幅提升用户在网站中或跨网站进行导航的体验,从而对网站的转化率和留存率等商业指标做出正向的改变。
先导知识在了解如何使用以及应该何时使用 Speculation Rules API 之前,我们需要对一些重要概念有初步的了解。
浏览器工作的大致原理浏览器的工作原理是个非常庞大且深奥的话题,但这里我们只需要对此有一个最基本的简略认识即可。大致来说,用户使用浏览器访问网页可以拆解为如下几个步骤:
导航:用户在地址栏输入 URL 或点击链接,浏览器解析目标网址的 DNS 并向对应 IP 地址发送请求、建立连接。响应:目标网站服务器接到用户浏览器请求,根据请求的路径返回相应的资源数据。解析:浏览器收到服务器发送的数据包,并解析出相应文件;再根据解析出的 HTML、CSS、JS 等文件,构建 DOM 树和 CSSOM 树,并将 JS 构建为抽象语法树或进一步编译为字节码。渲染:将 DOM 树和 CSSOM 树合并为渲染树,并使用 CPU 或 GPU 将树的各个节点绘制到屏幕上。在下文中,为表述方便,我们进一步精简,将第一步和第二步统称为请求网络资源,将后两步统称为渲染。
Core Web VitalsCore Web Vitals 是用于衡量网页性能的最核心指标。它可以用量化的方式反应用户访问网页时的“快慢”,衡量主观的“用户体验”。它即作为评价标准,影响了搜索引擎收录网页的权重,直接干预网页在自然流量下的推广水平;又可以成为开发人员和项目管理人员自检的指标,评估网页响应速度,进而优化其背后的留存转化商业漏斗模型。
最大内容渲染(Largest Contentful Paint, LCP):从用户请求网址到在视口中渲染最大可见内容元素所需的时间。通常来说,网页上占最大面积的内容一般是主要内容,比如博客网站中博文占据面积最大,相册网站中图片占据面积最大。通过评估 LCP,可以估算用户需要多长时间才能看到比较完整的网页结构。通俗地说,LCP 可以简单理解为“网页大致加载完成所需时间”。交互响应时间(Interaction to Next Paint, INP):网页动态内容响应用户操作、作出反应的时间。大多数网站中都有需要用户进行操作的内容,例如提交表单、点击按钮等;而现代网页对这种情况一般不使用跳转,而是使用异步请求和更新网页内容。INP 表示网页从用户点击到重新绘制内容的时间,可以评价网页“操作起来是否顺畅”、用起来“卡不卡”。累计布局偏移(Cumulative Layout Shift, CLS):网页整个生命周期内意外发生的布局偏移之和。例如,当网页异步加载资源导致内容位置发生非预期的移动,或交互造成的内容改变让用户容易产生误操作(当然,前者是前端开发者可以优化的,后者就需要产品经理和设计师的评估和修改);也就是我们常说的“网页内容跳变”。预加载和预渲染从最简单定义来说,预加载就是在用户访问特定网页前,浏览器提前将静态资源加载好;预渲染则更进一步,直接利用加载好的资源完成了渲染,用户真正访问时只需要直接呈现。 这里我们需要分两方面来讲——混合式开发中开发者主动使用的预加载和预渲染技术,以及之前版本 Chrome 浏览器中就已引入的预加载和预渲染技术。
混合式开发中预加载和预渲染做过微信或 QQ 小程序、Hybrid 应用和 Electron 等广义前端项目的小伙伴应该对这两个概念并不陌生。在这些场景下,我们或多或少地会使用到预加载和预渲染。
我们都知道,纯 web 应用有一个先天的不足——一切资源的呈现都依赖网络资源的加载,加载完成后浏览器再依据代码和资源进行渲染。如果是没有任何缓存资源的受访,或是网络环境较差情况下的访问,那网页的 LCP 和 CLS 会非常大,严重影响用户体验。
在传统的纯 web 开发中,我们当然无法预知永久何时会访问我们的网页,也就无法对我们的网页内容进行预加载和预渲染;但在上面所列举的混合式开发中,当 web 开发者具备一定的对客户端进行控制或自定义的能力时,我们就可以提前预判用户有可能下一步打开的页面并提前加载资源甚至提前渲染好页面。
之前版本的 Chrome 中的预加载和预渲染在将 Speculation Rules API 开放给 web 开发者之前, Google 已经在之前版本的 Chrome 中使用了很久的预加载和预渲染技术。
在很早的版本中,开发者就可以通过在网页中加入 <link rel="prefetch" href="/next-page/"> 标签,指示浏览器对标签所指向的 URL 进行预加载,提前把需要跳转到的网页所需要的静态资源准备好,保证用户跳转过去后立刻开始渲染、不需要花额外的时间在网络资源请求上。
此外,用户在 Chrome 的地址栏输入 URL 时,Chrome 会根据用户之前的访问记录,判断用户当前输入的 URL 是否能匹配上之前曾访问过的 URL。根据用户输入的内容计算每条能匹配的历史记录被命中的概率,当这个概率足够高时, Chrome 会把这个 URL 对应的网页资源请求下来,并直接渲染出来,当用户敲下回车确认网址的那一刻直接实现“秒开”。简单地说,其内部处理机制类似于新开了一个隐藏的标签页来显示用户有极大可能将要访问的那个网页,当用户真的访问的时候,直接把这个隐藏标签页显示出来并切换到前台。
综上,Chrome 在之前的版本中已经实现了“由开发者主动要求的预加载资源”技术和“Chrome 基于历史记录和 URL 匹配或然率预测的预加载及预渲染”技术。而现在,借助 Speculation Rules API,我们也可以要求 Chrome 对我们指定的 URL 进行预加载和预渲染。
Spectulation Rules API 的工作原理和用法Spuculation Rules API 是一个浏览器 API。对前端开发者而言,使用它是一件成本极低的事情,因为大部分事情会由浏览器来完成,你需要做的只是告诉浏览器需要完成哪些工作。这里我们简单说明一下它的工作原理,以及我们应该如何使用它。
浏览器是怎么实现 Speculation Rules API 的在支持 Speculation Rules API 的浏览器中,存在一种新的 script 类型,用 type="speculationrules" 声明。这种 script 以 JSON 结构体的形式表示,它允许开发者告诉浏览器:“我的访问者接下来很可能访问哪个链接”。
随后浏览器会根据开发者声明的内容,对开发者希望预渲染的内容提前加载资源并完成渲染——就像前文提到过的,这个过程可以简单理解为浏览器在后台打开了一系列隐藏的标签页,在网站访问者需要跳转过去的时候再直接把这些标签页切换到前台打开。
当然,从上面的描述你也可以想象,预渲染是一个十分消耗网络资源和计算资源的操作。因此,在浏览器的具体实现上,还会根据用户设备状态(剩余电量、设备性能等)和网络状态(当前页面是否已加载完、是否处于弱网状态、是否使用按流量计费的网络),按照其推测规则预估用户访问每个被声明的网页的概率,进而对访问概率高的网址进行预加载。
如何使用 Speculation Rules API使用 Speculation Rules API 非常简单,你只需要在 header 中添加一段 script 就可以,script 的内容是一段 JSON 格式配置,指示需要预加载的 URL:
<script type="speculationrules"> { "prerender": [ { "urls": ["page2.html", "page3.html"] } ] }</script>上面的例子使用了当前域的相对路径。其实,使用外部域也是可以的。
<script type="speculationrules"> { "prerender": [ { "urls": ["https://potatofield.cn"] } ] }</script>甚至可以使用更加复杂的规则,它支持简单的正则,可以用类似数据库查询的与或逻辑来匹配网页中所有的 <a /> 标签,甚至可以使用 CSS 选择器来过滤链接。
<script type="speculationrules">{ "prerender": [{ "where": { "and": [ { "href_matches": "/*" }, { "not": {"href_matches": "/wp-admin"}}, { "not": {"href_matches": "/*\\?*(^|&)add-to-cart=*"}}, { "not": {"selector_matches": ".do-not-prerender"}}, { "not": {"selector_matches": "[rel~=nofollow]"}} ] } }]}</script>上面的案例应该不难懂,它指示浏览器匹配路径不包含 /wp-admin 和 add-to-cart= 的链接,以及添加了 .do-not-prerender 的 CSS 类名和 rel~=nofollow 属性的也会被过滤。
你甚至可以使用 eagerness 参数来告诉浏览器何时进行推测(这个推测指的是浏览器对用户访问 URL 的概率进行估算):
<script type="speculationrules">{ "prerender": [{ "where": { "and": [ { "href_matches": "/*" }, { "not": {"href_matches": "/wp-admin"}}, { "not": {"href_matches": "/*\\?*(^|&)add-to-cart=*"}}, { "not": {"selector_matches": ".do-not-prerender"}}, { "not": {"selector_matches": "[rel~=nofollow]"}} ] } }]}</script>上面的例子中 eagerness 被设置为 moderate,此外它还有以下几个参考值:
immediate :此选项用于尽快推测,即在遵守推测规则后立即进行推测。eager :其行为与 immediate设置完全相同,但将来,我们希望将其放置在immediate和moderate 之间。moderate :如果将指针悬停在某个链接上 200 毫秒(如果指针悬停在链接上的时间较短,那么它会执行推测;如果是在移动设备上没有 hover 事件,则取决于按住事件)。conservative :此类型基于指针或轻触操作推测。当然,如果你只需要浏览器帮你完成预加载而不需要预渲染,也可以只使用 prefetch。
<script type="speculationrules">{ "prefetch": [ { "urls": ["next.html", "next2.html"] } ]}</script>何时使用 Speculation Rules API作为一个高效、易用且强大的 API,或许你已经迫不及待想要付诸实践了。不过,在此之前,我们还需要关注一下兼容性问题,看看这种技术方案的优势和局限,从而分辨最适合和不宜使用它的需求场景。
兼容性问题不幸的是,目前只有 Chome 以及 Chromium 内核的浏览器支持它;但万幸的是,Chrome 和 Chromium 内核的浏览器支持它。
当然,不被 Safari 和 Firefox 兼容并不是什么致命的缺陷。因为用于声明和调用 Speculation Rules API 的 script 是非阻塞性的,所以当浏览器环境无法对该功能提供支持时,会自动进行优雅降级。换言之,使用 Chrome 或 Chromium 内核的用户将获得极佳的体验,而不使用这些浏览器的用户也不会遇到任何 bug 和额外的体验劣化。虽然在合适的场景引入 Speculation Rules API 只能造福一部分用户,但这并不会让另一部分用户蒙受任何损失——所以何乐而不为呢?
性能和开销前文已经做过说明,因为 Speculation Rules API 的大致工作原理是真的完成一遍静默状态下隐藏的网页加载和渲染,所以这一操作占用的资源是比较高的。
试想一下,你是一位正在使用手机浏览网页的用户——你的电池剩余电量有限,并且你正在使用按照流量计费的网络。这个时候,网页正在“贴心”地为了你的进一步使用体验,在后台偷偷摸摸加载、消耗你所剩不多的电量和流量。把自己代入这个情景,你会不会想要问候网站开发者的八辈儿祖宗?
局限性另外,作为开发者,我们对 Speculation Rules API 的使用还是有一定局限性的。
它支持开发者自定义预加载和预渲染的网址,但是允许声明的网址数量是有限的——显然,这是为了防止开发者对该 API 的滥用,过度消耗设备计算资源和网络资源。目前,允许开发者声明的预渲染网址数量是 10 个,预加载网址数量是 50 个。
因为预渲染的网页是在后台完成加载和渲染的,因此一以依赖用户操作和反馈的代码是无法执行的——诸如 alert 之类的弹窗就不要想了。
什么场景适合 Speculation Rules API尽管在兼容性和资源开销方面不那么完美、有一定的局限性,但这样一个宝藏 API,用好了还是可以显著提升用户体验的。要衡量一个页面适不适合用 Speculation Rules API,关键看以下两点:
用户访问的设备和网络状况是否可以忽略额外的计算和网络资源占用用户点击链接跳转到下一页的概率大不大我们可以用一些更具体的例子来说明:
校园网或办公内网页面很显然适合这种技术。因为这些场景下用户基本不需要担心流量问题和充电问题;而且用户需要完成办公流程或获取学习资料,大概率会执行多次跳转,点击链接的可能性是可以被预判的。超市扫码展示会员资料的页面或许并不需要。这种场景下用户极有可能使用的是用流量计费的网络,并且电池不一定充裕;用户展示会员码之后,再跳转访问其他页面的可能性也不高。各种网站的登录页、注册页很多时候也是合适的。因为用户注册或登录完,极大概率会返回主页或个人资料页(具体哪个页面取决于开发者的设计)。Speculation Rules API 是个易用且效果神奇的 API。在合适的场景用合理的方式使用,你会收获非一般的用户体验的。
作者:张志毅
来源-微信公众号:洋芋田
出处:https://mp.weixin.qq.com/s/5eBcEtGTDr4pu_MYdbL05A