likes
comments
collection
share

油管、BBC 都在用的优化技术:fetchPriority

作者站长头像
站长
· 阅读数 59

看了看油管的网站,发现它们用了这个属性,解决了之前怎么设置资源优先级的困扰。

油管、BBC 都在用的优化技术:fetchPriority

油管、BBC 都在用的优化技术:fetchPriority

简介

我们都知道,在浏览器解析网页并开始发现和下载资源(如图片、脚本或CSS)时,它会为这些资源分配一个获取优先级,以尝试以最优顺序下载资源。这些优先级可以取决于资源的类型以及其在文档中的位置。例如,在视口内的图片可能具有High的优先级,在<head>中的<link>元素加载的CSS可能具有Very High的优先级。浏览器在分配优先级方面表现得相当不错,但在某些情况下可能不是最优的。

Fetch Priority 可以在以下几个关键领域发挥作用:

提高图片LCP的优先级: 在 img 元素上指定 fetchpriority="high",可以使 LCP 尽早的触发。

使用更好的语义来增加异步脚本的优先级: 这比通常使用的 <link rel="preload"> 更有效。

降低后加载脚本的优先级: 这样可以更好地与图片进行顺序加载。

以前,我们会使用 preloadpreconnect 对资源优先级有一些影响, 但是这种影响时有限的。Fetch Priority 是 Resource Hints 的补充,但是理解它们的使用位置很重要。

Preload 可以让你告诉浏览器你想要在关键资源被自然发现之前就加载它们。这对于不容易发现的资源特别有用,例如样式表中包含的字体、背景图或从 script 加载的资源。

Fetch Priority 是一种基于标记的信号(设置 fetchpriority 属性),可以用它告诉特定资源的相对优先级。您还可以通过 JavaScript 和 Fetch API 使用这些提示,Fetch API 是通过设置 priority 属性。Fetch Priority 还可以与 preload 配合使用。比如,在样式表中包含的 LCP 图片即使使用了预加载,但是它的优先级仍然很低。如果它被其他早期低优先级资源推迟,可以使用 Fetch Priority 来早地加载图像。

// 几种使用方式 
<img src="/images/in_viewport_but_not_important.svg" fetchpriority="low" alt="I'm an unimportant image!">  
   
<link rel="preload" href="/js/script.js" as="script" fetchpriority="low">  
  
<script>  
    fetch('https://example.com/', {priority: 'low'})
    .then(data => {});  
</script>

资源优先级

资源下载顺序取决于浏览器为页面的每个资源分配的优先级。不同的因素会影响优先级计算逻辑。

  • CSS、字体、脚本、图片和第三方资源分配不同的优先级。
  • 在文档中引用资源的位置或顺序也会影响资源的优先级。
  • preload 资源提示有助于浏览器更快地发现资源,从而在文档加载之前加载资源,并影响优先级。
  • script 设置了 async 和 defer 也会影响优先级

当前大多数资源在Chrome中的优先级和顺序

布局阻塞在布局阻塞阶段加载在布局阻塞阶段逐个加载资源
Blink 优先级VeryHighHighMedium Low VeryLow
DevTools 优先级HighestHighMedium Low Lowest
主要资源
CSS*** (early**)CSS*** (late**) ## CSS (mismatch)
Script (early** or not from preload scanner)Script (**late) Script (async) ##
FontFont (preload)
Import
视口中的 Image## Image ##
## Media ##
## SVG document ##
## ## Prefetch
Preload*
XHR (sync)XHR/fetch* (async)
  1. '*' 使用 as 进行预加载或使用了"type"的 fetch 会使用它们请求的类型的优先级(例如,预加载 as="stylesheet" 将使用 Highest 优先级)。如果没有 "as",它们会表现得像 XHR。

    • fetch('image.jpg', { type: 'image/jpeg' }) ,浏览器会根据请求的资源类型来确定它的优先级。

    • <link rel="preload" href="styles.css" as="style">

  2. '**' "Early": 在请求任何非预加载图像之前的请求("late" 是之后)

  3. '***' 如果 CSS 的媒体查询类型不匹配,就不会被预加载扫描器获取,并且只会在主解析器到达时处理,这通常意味着它会被很晚地获取并且具有"late"优先级。

解释下第3点: <link rel="stylesheet" href="styles.css" media="print"> 在这个link中,styles.css 的媒体类型为 print,而浏览器在预加载时可能会忽略它,因为当前页面加载的是 "screen" 媒体类型的样式。只有当页面主解析器达到 "styles.css" 样式表时,它才会被处理,这可能发生得很晚,因此它的优先级可能是"late"。

看下前后的优先级:

油管、BBC 都在用的优化技术:fetchPriority

油管、BBC 都在用的优化技术:fetchPriority

油管、BBC 都在用的优化技术:fetchPriority

什么时候需要用 fetchPriority 🍒

首先,了解浏览器的优先级逻辑可以帮助你调整下载顺序。通过以下方式来控制浏览器的优先级计算,从而改善性能和核心 Web Vitals:

  1. 根据希望下载它们的顺序,放置资源标签,如
  2. 用 preload 资源提示来尽早下载必要的资源,特别是那些浏览器不容易早期发现的资源。
  3. 用 async 或 defer 异步下载脚本,而不会阻塞其他资源。
  4. 懒加载屏幕以外的内容,以便浏览器可以为更重要的内容更快的下载

在某些情况下,这些方法可能不太够用,这时候可以尝试下 fetchPriority :

  1. 比如轮播图,一般刚开始就会出现在视口中,但不必都具有相同的优先级,只有第一个可见的图像需要比其他图像具有更高的优先级(YouTube 视频预览图同理)。

  2. 有的视口内的主要图像是 "Low" 优先级,这一般会能感受到明显延迟。在标记中提供Fetch优先级可以让图像以“高”优先级开始,并更早地开始加载。

    注意:CSS 中 background 中的 LCP 图像,仍然需要使用预加载(preload)。可以通过在预加载元素上添加 fetchpriority='high' 来与 Fetch Priority 结合使用,否则图像仍将以默认的“低”优先级开始加载。

  3. 将脚本声明为异步(async)或延迟(defer)。这样脚本就是“low”优先级。我们可以添加 fetchpriority提高它们的优先级,同时确保异步下载。

  4. 还可以使用 fetch 来异步获取资源或数据。fetch 是“High”优先级。但有时候,我们可能不希望所有的 fetch 都以“High”优先级执行,比如初始化页面时,同时请求几个接口,想要某一部分数据最快展示出来。

  5. 浏览器将CSS和字体看成“High”优先级,但是对于LCP来说,并非所有这些资源都同等重要或必需。可以使用Fetch Priority来降低其中一些资源的优先级。

兼容性

惨不忍睹,但是不影响使用

如果学到了新知识,麻烦点个 👍 和 ⭐

转载自:https://juejin.cn/post/7268070933893005370
评论
请登录