rel=preload

<link> 元素的 <link> 属性的 rel 属性的 preload 值允许您在 HTML 的 <head> 中声明提取请求,指定页面很快将需要的资源,您希望在页面生命周期的早期开始加载这些资源,在浏览器的主要渲染机制启动之前。这确保它们可以更早地可用,并且不太可能阻塞页面的渲染,从而提高性能。即使名称包含术语“加载”,它也不会加载和执行脚本,而只是将其安排以更高的优先级下载和缓存。

基础知识

您最常使用 <link> 加载 CSS 文件以使用样式设置您的页面

html
<link rel="stylesheet" href="styles/main.css" />

但是,在这里,我们将使用 relpreload,它将 <link> 变成我们想要的任何资源的预加载器。您还需要指定

  • 资源在`href` 属性中的路径。
  • 资源类型在`as` 属性中。

一个简单的示例可能如下所示(参见我们的JS 和 CSS 示例源代码,以及在线示例)。

html
<head>
  <meta charset="utf-8" />
  <title>JS and CSS preload example</title>

  <link rel="preload" href="style.css" as="style" />
  <link rel="preload" href="main.js" as="script" />

  <link rel="stylesheet" href="style.css" />
</head>

<body>
  <h1>bouncing balls</h1>
  <canvas></canvas>

  <script src="main.js" defer></script>
</body>

在这里,我们预加载 CSS 和 JavaScript 文件,以便在稍后页面渲染需要时立即可用。此示例很简单,因为浏览器可能会在与预加载相同的 HTML 块中发现<link rel="stylesheet"><script> 元素,但是当发现的资源越晚且资源越大时,好处就会更加明显。例如

  • 从 CSS 内部指向的资源,例如字体或图像。
  • JavaScript 可以请求的资源,例如导入的脚本。

preload 还有其他优点。使用as 指定要预加载的内容类型允许浏览器

  • 将其存储在缓存中以供将来请求使用,并在适当情况下重复使用资源。
  • 对资源应用正确的内容安全策略
  • 为其设置正确的Accept 请求头。

可以预加载哪些类型的内容?

可以预加载许多内容类型。可能的as 属性值为

  • fetch:通过 fetch 或 XHR 请求访问的资源,例如 ArrayBuffer、WebAssembly 二进制文件或 JSON 文件。
  • font:字体文件。
  • image:图像文件。
  • script:JavaScript 文件。
  • style:CSS 样式表。
  • track:WebVTT 文件。

注意:fontfetch 预加载需要设置crossorigin 属性;请参阅下面的支持 CORS 的获取

注意:有关这些值以及它们期望被哪些 Web 功能使用的更多详细信息,请参阅 HTML 规范 - 请参阅链接类型“preload”。另请注意,as 属性可以取值的完整列表受 Fetch 规范控制 - 请参阅请求目标

包含 MIME 类型

<link> 元素可以接受type 属性,其中包含元素指向的资源的 MIME 类型。这在预加载资源时特别有用 - 浏览器将使用type 属性值来确定它是否支持该资源,如果支持,则只下载它,否则忽略它。

html
<head>
  <meta charset="utf-8" />
  <title>Image preload example</title>

  <link rel="preload" href="flower.avif" as="image" type="image/avif" />
</head>
<body>
  <picture>
    <source src="flower.avif" type="image/avif" />
    <source src="flower.webp" type="image/webp" />
    <img src="flower.jpg" />
  </picture>
</body>

上面示例中的代码导致仅在支持的浏览器中预加载image/avif 图像 - 对于浏览器中具有image/avif 支持的用户,导致实际使用image/avif 图像(因为它是在指定的第一个<source>)。这使得希望为在浏览器中具有image/avif 支持的用户下载更小的图像。

请注意,对于浏览器同时支持image/avifimage/webp 的用户,如果在该代码中还指定了<link rel="preload" href="flower.webp" as="image" type="image/webp"> 元素,则会预加载image/avifimage/webp 图像 - 即使实际上只会使用其中一个。

因此,不建议为同一资源的多种类型指定预加载。相反,最佳实践是仅为大多数用户可能实际使用的类型指定预加载。这就是上面示例中的代码未指定为image/webp 图像预加载的原因。

但是,缺少预加载并不会阻止image/webp 图像被需要它的人使用:对于浏览器不支持image/avif 但支持image/webp 的用户,上面示例中的代码仍然会导致使用image/webp 图像 - 但它是在不也为大多数其他用户不必要地预加载的情况下实现的。

支持 CORS 的提取

预加载使用CORS 启用的资源(例如fetch()XMLHttpRequest字体)时,需要特别注意设置crossorigin 属性在你的<link> 元素上。即使获取不是跨域的,也需要将属性设置为与资源的 CORS 和凭据模式匹配。

如上所述,这适用的一种有趣情况是字体文件。由于各种原因,必须使用匿名模式 CORS 获取这些文件(请参阅字体获取要求)。

让我们以这种情况为例。您可以在 GitHub 上查看完整的示例源代码也可以在线查看)。

html
<head>
  <meta charset="utf-8" />
  <title>Web font example</title>

  <link
    rel="preload"
    href="fonts/cicle_fina-webfont.woff2"
    as="font"
    type="font/woff2"
    crossorigin />
  <link
    rel="preload"
    href="fonts/zantroke-webfont.woff2"
    as="font"
    type="font/woff2"
    crossorigin />

  <link href="style.css" rel="stylesheet" />
</head>
<body></body>

我们不仅在type 属性中提供 MIME 类型提示,而且还提供crossorigin 属性以确保预加载的 CORS 模式与最终的字体资源请求匹配。

包含媒体

<link> 元素的一个很好的功能是它们能够接受media 属性。这些可以接受媒体类型 或完整的媒体查询,允许你进行响应式预加载!

让我们来看一个例子(在 GitHub 上查看 - 源代码在线示例)。

html
<head>
  <meta charset="utf-8" />
  <title>Responsive preload example</title>

  <link
    rel="preload"
    href="bg-image-narrow.png"
    as="image"
    media="(max-width: 600px)" />
  <link
    rel="preload"
    href="bg-image-wide.png"
    as="image"
    media="(min-width: 601px)" />

  <link rel="stylesheet" href="main.css" />
</head>
<body>
  <header>
    <h1>My site</h1>
  </header>

  <script>
    const mediaQueryList = window.matchMedia("(max-width: 600px)");
    const header = document.querySelector("header");

    if (mediaQueryList.matches) {
      header.style.backgroundImage = "url(bg-image-narrow.png)";
    } else {
      header.style.backgroundImage = "url(bg-image-wide.png)";
    }
  </script>
</body>

我们在<link> 元素上包含media 属性,以便如果用户具有窄视口,则预加载窄图像,如果他们具有宽视口,则加载宽图像。我们使用Window.matchMedia / MediaQueryList 来执行此操作(有关更多信息,请参阅测试媒体查询)。

这使得字体更有可能在页面渲染时可用,从而减少了 FOUT(未设置样式文本的闪烁)。

这不必局限于图像,甚至不必是相同类型的文件 - 想得大一点!例如,如果用户在带宽和 CPU 可能会更有限的窄屏幕上,你可以预加载并显示一个简单的 SVG 图表,或者预加载一个复杂的 JavaScript 块,然后使用它来渲染交互式 3D 模型,如果用户的资源更丰富。

脚本和预加载

注意:如果你正在使用JavaScript 模块,请改用<link rel="modulepreload">

这些预加载的另一个优点是你可以使用脚本执行它们。例如,这里我们创建一个HTMLLinkElement 实例,然后将其附加到 DOM

js
const preloadLink = document.createElement("link");
preloadLink.href = "myscript.js";
preloadLink.rel = "preload";
preloadLink.as = "script";
document.head.appendChild(preloadLink);

这意味着浏览器将预加载myscript.js 文件,但尚未实际使用它。要使用它,你可以这样做

js
const preloadedScript = document.createElement("script");
preloadedScript.src = "myscript.js";
document.body.appendChild(preloadedScript);

当你想预加载脚本,但推迟执行到真正需要它的时候,这很有用。

规范

规范
HTML 标准
# link-type-preload

浏览器兼容性

BCD 表格仅在启用 JavaScript 的浏览器中加载。

另请参阅