rel=preload
<link>
元素的 <link>
属性的 rel
属性的 preload
值允许您在 HTML 的 <head>
中声明提取请求,指定页面很快将需要的资源,您希望在页面生命周期的早期开始加载这些资源,在浏览器的主要渲染机制启动之前。这确保它们可以更早地可用,并且不太可能阻塞页面的渲染,从而提高性能。即使名称包含术语“加载”,它也不会加载和执行脚本,而只是将其安排以更高的优先级下载和缓存。
基础知识
您最常使用 <link>
加载 CSS 文件以使用样式设置您的页面
<link rel="stylesheet" href="styles/main.css" />
但是,在这里,我们将使用 rel
值 preload
,它将 <link>
变成我们想要的任何资源的预加载器。您还需要指定
一个简单的示例可能如下所示(参见我们的JS 和 CSS 示例源代码,以及在线示例)。
<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
指定要预加载的内容类型允许浏览器
可以预加载哪些类型的内容?
可以预加载许多内容类型。可能的as
属性值为
fetch
:通过 fetch 或 XHR 请求访问的资源,例如 ArrayBuffer、WebAssembly 二进制文件或 JSON 文件。font
:字体文件。image
:图像文件。script
:JavaScript 文件。style
:CSS 样式表。track
:WebVTT 文件。
注意:font
和fetch
预加载需要设置crossorigin
属性;请参阅下面的支持 CORS 的获取。
注意:有关这些值以及它们期望被哪些 Web 功能使用的更多详细信息,请参阅 HTML 规范 - 请参阅链接类型“preload”。另请注意,as
属性可以取值的完整列表受 Fetch 规范控制 - 请参阅请求目标。
包含 MIME 类型
<link>
元素可以接受type
属性,其中包含元素指向的资源的 MIME 类型。这在预加载资源时特别有用 - 浏览器将使用type
属性值来确定它是否支持该资源,如果支持,则只下载它,否则忽略它。
<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/avif
和image/webp
的用户,如果在该代码中还指定了<link rel="preload" href="flower.webp" as="image" type="image/webp">
元素,则会预加载image/avif
和image/webp
图像 - 即使实际上只会使用其中一个。
因此,不建议为同一资源的多种类型指定预加载。相反,最佳实践是仅为大多数用户可能实际使用的类型指定预加载。这就是上面示例中的代码未指定为image/webp
图像预加载的原因。
但是,缺少预加载并不会阻止image/webp
图像被需要它的人使用:对于浏览器不支持image/avif
但支持image/webp
的用户,上面示例中的代码仍然会导致使用image/webp
图像 - 但它是在不也为大多数其他用户不必要地预加载的情况下实现的。
支持 CORS 的提取
预加载使用CORS 启用的资源(例如fetch()
、XMLHttpRequest
或字体)时,需要特别注意设置crossorigin
属性在你的<link>
元素上。即使获取不是跨域的,也需要将属性设置为与资源的 CORS 和凭据模式匹配。
如上所述,这适用的一种有趣情况是字体文件。由于各种原因,必须使用匿名模式 CORS 获取这些文件(请参阅字体获取要求)。
让我们以这种情况为例。您可以在 GitHub 上查看完整的示例源代码(也可以在线查看)。
<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 上查看 - 源代码,在线示例)。
<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
const preloadLink = document.createElement("link");
preloadLink.href = "myscript.js";
preloadLink.rel = "preload";
preloadLink.as = "script";
document.head.appendChild(preloadLink);
这意味着浏览器将预加载myscript.js
文件,但尚未实际使用它。要使用它,你可以这样做
const preloadedScript = document.createElement("script");
preloadedScript.src = "myscript.js";
document.body.appendChild(preloadedScript);
当你想预加载脚本,但推迟执行到真正需要它的时候,这很有用。
规范
规范 |
---|
HTML 标准 # link-type-preload |
浏览器兼容性
BCD 表格仅在启用 JavaScript 的浏览器中加载。
另请参阅
- 推测性加载,用于比较
<link rel="preload">
和其他类似的性能改进功能。 - 预加载:它有什么用? 由 Yoav Weiss 撰写