rel=preload

Baseline 廣泛可用 *

此特性已得到良好確立,並可在多種裝置和瀏覽器版本上執行。自 2021 年 1 月起,所有瀏覽器均已支援此特性。

* 此特性的某些部分可能存在不同級別的支援。

<link> 元素的 rel 屬性的 preload 值允許你在 HTML 的 <head> 中宣告抓取請求,指定頁面很快將需要的資源。你希望在頁面生命週期早期開始載入這些資源,趕在瀏覽器主要渲染機制啟動之前。這確保它們能更早可用,並且不太可能阻塞頁面渲染,從而提高效能。儘管名稱中包含“載入”一詞,但它並不會載入並執行指令碼,而只是以更高的優先順序安排其下載和快取。

基本原理

你最常使用 <link> 來載入 CSS 檔案以美化頁面

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

然而,這裡我們將使用 rel 值為 preload,它將 <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 的抓取請求

注意: HTML 規範中對這些值以及它們預期被哪些 Web 功能消費有更詳細的描述——請參閱 Link type "preload"。另請注意,as 屬性可接受的完整值列表受 Fetch 規範管理——請參閱 request destinations

包含 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字型)時,需要特別注意在你的 <link> 元素上設定 crossorigin 屬性。該屬性需要設定為與資源的 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="(width <= 600px)" />
  <link
    rel="preload"
    href="bg-image-wide.png"
    as="image"
    media="(width > 600px)" />

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

  <script>
    const mediaQueryList = window.matchMedia("(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
# 連結型別預載入

瀏覽器相容性

另見