本文介绍了使用Speculation Rules API进行Web性能优化的分层方法,包括prefetch和prerender的使用,以及如何根据网站规模和需求进行定制化的策略选择。文章还讨论了如何通过data-prefetch属性实现更精细的控制,以及实验结果的令人信服的表现。
文章介绍了Speculation Rules API的基本概念,包括prefetch和prerender两种推测加载类型,以及它们的目标和用途。
文章通过作者在实际项目中的经验,详细解释了如何将分层方法应用于Web性能优化,包括针对不同层次的需求选择合适的优化策略。
文章强调了使用data-prefetch属性来精细控制推测加载的重要性,并提供了具体的实现方法和示例代码。
文章分享了一周的实验结果,并分析了使用分层方法进行Web性能优化的效果,强调了这种方法的优雅性和满意度。
文章总结了使用分层方法进行Web性能优化的经验和教训,并展望了未来的发展方向和可能的改进点。
前言
规范化规则的分层方法是一种将 Web 性能优化策略分解为不同层次的技术。每个层次都专注于特定类型的性能问题和优化策略,这样可以更有效地识别和解决性能瓶颈。今日前端早读课文章由 @飘飘翻译分享。
明天你会来前端 FEDay 吗?
译文从这开始~~
我一直喜欢使用简单的 Web 平台功能做一些不太常规和巧妙的事情,以最大限度地发挥它们的作用。从构建最小的兼容 LCP ,懒预加载 CSS,或者使用像素 GIF 来跟踪非 JS 的用户和失效的 CSS,我发现从有用的东西中创造出有用的东西很有乐趣。
最近,我一直在使用 Speculation Rules API 进行类似的游戏。
投机行为规则
我不想在这篇文章中深入讨论 Speculation Rules API,但需要了解的关键点是,它提供了两种推测加载类型 —— prefetch 和 prerender —— 其最终目标如下:
记住这两个常识将会非常有帮助 —— prefetch 用于减少 TTFB;prerender 用于 LCP。这使得 LCP 成为两者中较轻的选项,而 TTFB 则需要更多的资源。
对于本文的目的来说,这些就足够了。
对 csswizardry.com 的猜测
自从推测规则可用以来,我在这个网站上对其进行了一些不太令人满意的运用:
1、预渲染主页上的最新文章:
<script type=speculationrules>
{
"prerender": [
{
"urls": [ "/2024/12/a-layered-approach-to-speculation-rules/" ]
}
]
}
script>
2、预渲染页面上的下一篇和上一篇文章,就像这样的页面:
<script type=speculationrules>
{
"prerender": [
{
"urls": [
"/2024/12/a-layered-approach-to-speculation-rules/",
"/2024/11/core-web-vitals-colours/"
]
}
]
}
script>
在这种情况下,我明确预渲染了命名和已知的 URL,对潜在且可能的用户旅程有一个大致的设想 —— 我正在预热我认为可能是访客下一页的内容。
虽然这两点都是实用且有益的,但我想做得更多。我的网站虽然看起来不太明显,但实际上有两面性:面向像你这样的普通用户的博客部分,以及面向潜在客户的商业部分。虽然引导人们快速浏览文章内容很棒,但我能否为浏览网站其他部分的访客提供更多帮助呢?
我最近将我的 “猜测规则” 扩展为:
-
不要在页面上添加任何内部链接,并且;
-
在鼠标悬停时,不要显示任何其他内部链接。
这种相对不加选择的方法所覆盖的范围比列出的 URL 要广泛得多,它不是只关注页面上的链接地址,而是会留意页面上的任何内部链接。
<script type=speculationrules>
{
"prefetch": [
{
"where": {
"href_matches": "/*"
},
"eagerness": "immediate"
}
],
"prerender": [
{
"where": {
"href_matches": "/*"
},
"eagerness": "moderate"
}
]
}
script>
这种稍显分层的方法使我们能够为页面上所有内部链接的 TTFB 成本进行合理支付,并为页面上任何我们悬停的内部链接的 LCP 成本进行合理支付( moderate )。这些是相当广泛的规则,因为它们适用于页面上任何匹配
/*
的链接 —— 所以任何根相对链接。
这种方法对我很有效,因为我的网站完全是静态生成的,并且由 Cloudflare 的边缘服务器提供服务。我也没有大量的流量,因此任何地方的服务器负载增加的风险都非常小。对于拥有大量流量且后端高度动态(数据库查询、API 调用、缓存不足)的网站来说,这种方法可能过于宽松。
多层次方法
在最近的一个客户项目中,我想将这个想法进一步深化。他们的网站规模庞大且相对复杂(许多不同的产品线都归属于同一个域名),拥有大量的流量和相当复杂的后端基础设施。因此,我们必须更加谨慎地考虑问题。
【第2875期】HTML性能优化-Prerender2.0机制解读
选择策略
他们是一个大型网站,因此采用用户同意的方式是更好的选择。这种类似通配符的匹配方式会过于贪婪,因为不同的页面包含的链接数量差异极大,很难预测在整个网站范围内增加的额外负担。
可以说,加入 Speculations 最简单的方法是使用选择器。例如,我们可以使用类:
<a href class=prefetch>Prefetched Linka>
<a href class=prerender>Prerendered Linka>
相应的推测规则:
<script type=speculationrules>
{
"prefetch": [
{
"where": {
"selector_matches": ".prefetch"
},
...
}
],
"prerender": [
{
"where": {
"selector_matches": ".prerender"
},
...
}
]
}
script>
需要注意的是,prerender 已经包含了 prefetch 阶段,因此你不需要同时使用
class="prefetch prerender"
;只需要其中一个就足够了。
然而,我喜欢这种模式的自我实现:
<a href data-prefetch>Prefetched Linka>
<a href data-prefetch=prerender>Prerendered Linka>
而它们各自的猜测规则是:
<script type=speculationrules>
{
"prefetch": [
{
"where": {
"selector_matches": "[data-prefetch]"
},
...
}
],
"prerender": [
{
"where": {
"selector_matches": "[data-prefetch=prerender]"
},
...
}
]
}
script>
它将所有逻辑都包含在一个
data-prefetch
属性中,且
data-prefetch=prerender
匹配的冗余性,根据定义,不是问题(与
dns-prefetch
和
preconnect
的情况类似,尽管它们的韦恩图中有重叠,但它们仍然相处得很好)。
【第1053期】Preload,Prefetch 和它们在 Chrome 之中的优先级
分层
有了这个简单的用户选择机制后,我想看看是否有办法巧妙而有效地进一步增强其功能,而不需要进行任何额外的配置。仅凭这两个属性,我可以做些什么来最大化 “猜测规则” 的优势呢?
我的想法是,如果我们明确标记了
data-prefetch
和
data-prefetch=prerender
,是否可以按需升级前者为后者?当页面加载时,浏览器立即满足其预取和预渲染,但如果有人将预加载的链接悬停并展开,是否可以将其升级为完整的预渲染操作?
简单。
然后,我们是否可以将任何其他内部链接从无到有,升级为按需预取?
也很容易!
以积极性由强至弱的顺序进行考虑,同时牢记我们提到的两个常识,我们思考我们正在实现的目标的最佳方式是:
1、立即为我们选择加入的任何链路支付 LCP 费用。
"prerender": [
{
"where": {
"selector_matches": "[data-prefetch=prerender]"
},
"eagerness": "immediate"
},
...
]
2、立即为我们选择加入的任何链接支付 TTFB 费用。
"prefetch": [
{
"where": {
"selector_matches": "[data-prefetch]"
},
"eagerness": "immediate"
},
...
],
3、按需支付 LCP 费用,以补偿我们已经支付了 TTFB 费用的任何链接:
"prerender": [
...
{
"where": {
"selector_matches": "[data-prefetch]"
},
"eagerness": "moderate"
}
]
4、按需付费,为任何其他内部链接支付 TTFB 成本:
"prefetch": [
...
{
"where": {
"href_matches": "/*"
},
"eagerness": "moderate"
}
],
现在,客户能够使用
data-prefetch=prerender
属性预渲染极有可能或被鼓励执行的导航操作。(例如在顶级导航或首页上的号召性用语)。
不太可能但还是比较合理的热身选项(例如子导航中的项目)可以简单地使用
data-prefetch
。
其余的都只是一些空荡荡的节点,所有链接(除了已经达到最大值的
data-prefetch=prerender
之外)会根据需要升级到下一个类别。
将它们按照所需的格式和顺序排列在一起后,我们的 “猜测” 规则如下所示:
<script type=speculationrules>
{
"prefetch": [
{
"where": {
"selector_matches": "[data-prefetch]"
},
"eagerness": "immediate"
},
{
"where": {
"href_matches": "/*"
},
"eagerness": "moderate"
}
],
"prerender": [
{
"where": {
"selector_matches": "[data-prefetch=prerender]"
},
"eagerness": "immediate"
},
{
"where": {
"selector_matches": "[data-prefetch]"
},
"eagerness": "moderate"
}
]
}
script>
我们可以将这些规则应用到这个示例页面上: