跳到主要内容

rel

2024年04月30日
柏拉文
越努力,越幸运

一、认识


rel 属性定义了所链接的资源与当前文档的关系,在 <a><area><link> 元素上有效。支持的值取决于拥有该属性的元素。

二、语法


三、属性值


3.1 prefetch

资源预读取(Prefetch是一种浏览器优化技术,用于在页面加载过程中提前请求并缓存未来可能需要的资源,以减少后续页面导航或操作时的延迟。通过使用 Prefetch,浏览器可以主动去加载和缓存当前页面附加资源(如脚本、样式表、图片等),以便在用户导航到下一个页面时能够更快地获取这些资源。这样可以提高用户体验,因为用户在导航到下一个页面时不需要等待资源的加载,而是能够立即渲染页面。Prefetch 指定用户代理应预先获取并缓存目标资源,因为后续的导航可能需要它。资源预获取强调的是对后续页面关键资源的提前获取。Prefetch 可以强制浏览器在不阻塞 documentonload 事件的情况下请求资源。

Chrome 中,如果用户导航离开一个页面,而对其他页面的预取请求仍在进行中,这些请求将不会被终止。

prefetch 加载的是接下来页面可能会使用的资源,因此优先级最低,为Lowest

<link rel="prefetch" as="style" href=""/>
<link rel="prefetch" as="script" href=""/>

3.2 preload

资源预加载(preload 是一种浏览器优化技术,用于在页面加载过程中提前加载当前页面所需的关键资源,以加速页面渲染和提高用户体验。通过使用 preload,开发者可以指定一些重要资源在页面加载时优先获取,以便在需要时能够立即使用。指定用户代理必须根据 as 属性给出的潜在目的地(以及与相应目的地相关的优先级),为当前导航预先获取和缓存目标资源。资源预加载 强调的是对当前页面关键资源的提前加载。

preload 加载的是本页即将要使用的资源, 因此优先级要比 prefetch 高。但具体是多少,要看加载的资源的类型:

<link rel="preload" href="main.js" as="script" />
<link rel="preload" href="myfont.ttf" as="font">
<link rel="preload" href="style.css" as="style" />
<link rel="preload" href="example.png" as="image" />

其中,JSCSS和字体文件preload的优先级是High,而image类型的资源的优先级是Low,这个和页面中JS资源的加载不同,对于页面内直连的JS文件,其加载优先级是Medium,而IMG图片则是HighCSSHighest

如上所示: 使用as属性预加载的资源将具有与它们请求的资源类型相同的资源优先级。 例如 preload as =“style” 将获得最高优先级,而 as =“script” 将获得低优先级或中优先级。 这些资源也遵循相同的CSP策略(例如脚本受 script-src 约束)。不带 as 属性的 preload 的优先级将会等同于异步请求。

3.3 modulepreload

资源预加载 modulepreload 对于原生 ESM 模块,浏览器提供了 modulepreload来进行预加载:

<link rel="modulepreload" href="main.js" />

3.4 prerender

prerender 指定用户代理应预先获取目标资源,并以有助于在未来提供更快的响应的方式处理它。**预渲染(prerender)**是一种网页优化技术,它允许浏览器在用户导航到页面之前提前加载并渲染页面内容。这样做可以显著提高页面加载速度和用户体验。

四、扩展


4.1 资源加载优先级

Priority Hints(优先级提示)是一种用于指导浏览器资源加载顺序的技术。它允许开发者向浏览器提供有关资源加载优先级的建议,以便浏览器更好地决定哪些资源应该优先加载。通过使用 Priority Hints,开发者可以提高关键资源的加载速度,从而改善页面性能和用户体验。

HTML 中,可以使用 <link> 元素的 rel 属性来添加 Priority Hints。具体来说,以下是一些常用的 Priority Hints 值:

  • preload: 建议浏览器在页面加载过程中尽早加载该资源。

  • prefetch: 建议浏览器在后台加载该资源,以备将来使用。

  • prerender: 建议浏览器预渲染该资源,以提前生成即将展示给用户的页面。

4.2 五层加载优先级

Chrome浏览器中的5层优先级指的是网络请求的优先级,这些优先级决定了浏览器在处理网络请求时的顺序和优先级。以下是Chrome浏览器中网络请求的5个优先级:

  • 最高优先级(Highest: 该优先级通常用于处理关键资源,如页面的主要 HTMLJavaScriptCSS 文件。这些资源对于页面的加载和渲染至关重要。

  • 较高优先级(High: 该优先级通常用于处理一些重要的资源,如页面中需要立即展示的图片、字体等。

  • 默认优先级(Medium: 大多数网络请求的默认优先级,包括大多数的静态资源和异步加载的资源。

  • 较低优先级(Low: 该优先级通常用于处理一些不太重要的资源,如异步统计脚本、广告等。

  • 最低优先级(Lowest: 该优先级通常用于处理一些可延迟加载的资源,如某些后台任务、预取资源等。

这些优先级可以帮助浏览器更好地处理网络请求,确保关键资源能够尽快加载并渲染,提高用户的页面加载体验。在实际开发中,可以通过设置合适的资源加载优先级来优化页面加载性能。

我们可以Chrome浏览器的开发者工具,在 Network 面板中可以看到每一个请求的优先级,如下图所示。

Preview

如果你发现你的浏览器没有上图选中的列表,试试右键面板,然后访问下图所示的菜单项进行开启。

Preview

六、问题


6.1 如何正确使用 prefetch 和 preload ?

preload 使用 as 属性,不然将不会从中获益。如果在指定要 preload 的内容(例如脚本)时未提供有效的 as,则最终将获取两次。

这是工具的一个很好的例子,而不是规则。 preload 的文件数量取决于加载其他资源时网络内容、用户的带宽和其他网络状况。尽早 preload 页面中可能需要的文件,对于脚本,preload 你的关键模块是很好的,因为它将获取与执行分开,而仅仅使用 <script async> 不会这样做,因为它会阻止窗口的 onload 事件。你可以 preload 图像、样式、字体和媒体。最重要的是,作为一名页面作者,你可以更好地控制提前获取页面所需要的信息。

6.2 可以使用 preload 让 CSS 样式立即生效吗?

当然可以,preload 支持基于异步加载的标记,使用 <link rel=”preload”> 的样式表可以使用 onload 事件立即应用于当前文档:

<link rel="preload" href="style.css" onload="this.rel=stylesheet">

6.3 prefetch 可以作为 preload 的后备方案吗?

不要用 prefetch 作为 preload 的后备方案 ,它们适用于不同的场景,常常会导致不符合预期的二次获取。使用 preload 来获取当前需要任务否则使用 prefetch 来获取将来的任务,不要一起用。

以下的代码段可以判断 <link rel=”preload”> 支持情况:

const preloadSupported = () => {
const link = document.createElement('link');
const relList = link.relList;
if (!relList || !relList.supports)
return false;
return relList.supports('preload');
};

FilamentGroup 也有一个 preload 检测器 ,作为他们的异步 CSS 加载库 loadCSS 的一部分。

6.5 preload 或者 prefetch 什么情况下会导致二次获取?

  1. prefetch 作为 preload 的后备方案来使用, 它们适用于不同的场景,常常会导致不符合预期的二次获取。

  2. 如果在指定要 preload 的内容(例如脚本)时未提供有效的 as,则最终将获取两次。

  3. preload 字体不带 crossorigin 也将会二次获取, 确保在使用 preload 获取字体时添加 crossorigin 属性,否则将二次下载。 他这个请求使用匿名的跨域模式。 即使字体与页面位于同个域 下,也建议使用。也适用于其他域名的获取(比如说默认的异步获取)。

6.6 可以用 HTTP2 的服务器推送来代替 preload 吗?

当你知道资源的精确加载顺序时使用推送,并让 service worker 拦截可能导致再次推送缓存资源的请求。 使用 preload 可以使资源的开始下载时间更接近初始请求 - 这对所有的资源获取都有用。

我们假设浏览器正在加载一个页面,页面中有个 CSS 文件,CSS 文件又引用一个字体库,对于这样的场景,

若使用 HTTP/2 PUSH,当服务端获取到 HTML 文件后,知道以后客户端会需要字体文件,它就立即主动地推送这个文件给客户端,如下图:

Preview

而对于 preload,服务端就不会主动地推送字体文件,在浏览器获取到页面之后发现 preload 字体才会去获取,如下图:

Preview

虽然推送很有效,但它不像 preload 那样对所有的情况都适应。

推送不能用于第三方资源的内容,通过立即发送资源,它还有效地缩短浏览器自身的资源优先级情况。在你明确的知道在做什么时,这应该会提高你的应用性能,如果不是很清晰的话,你也许会损失掉部分的性能。

6.7 Js 中自定义的 preload 与原本的 rel = preload 有什么区别?

preload 解耦从 JS 处理和执行中获取资源。 因此,preload 在标记中声明以被 Chrome preload 扫描器扫描。 这意味着在许多情况下,在 HTML 解析器甚至到达标签之前,将获取预加载(具有指示的优先级),这使它比自定义预加载实现更强大。

6.8 preload 请求头是什么?它与 preload 标签相比如何?它与 HTTP2 服务器推送有什么关系?

与其他类型的链接一样,preload 链接即可以使用 HTML 标记 或 HTTP 标头。 在任何一种情况下,preload 链接都会指示浏览器开始将资源加载到内存缓存中,这表明该页面有很高可能性使用该资源,并且不希望等待预加载扫描程序或解析程序发现它。

当金融时报在它们的网站使用 preload HTTP 头时,他们节约了大约 1s 的显示片头图片时间。

Preview

如上所示: 1 没有使用 preload, 2 使用了 preload

你可以使用任何一种形式提供 preload 链接,但是你应该知道一个重要区别:如规范所允许的,许多服务器在遇到 HTTP 头的 preload 链接时会触发 HTTP/2 服务器推送。 HTTP/2 推送的性能影响不同于普通的预加载,所以你要确保没有发起不必要的推送。

你可以使用 preload 标签来代替 preload 头以避免不必要的推送,或者在你的 HTTP 头上加一个 nopush 属性。