<script type="speculationrules">

實驗性: 這是一個 實驗性技術
在生產環境中使用此功能前,請仔細檢視 瀏覽器相容性表

speculationrulestype 屬性在 <script> 元素中的值,表示元素主體包含推測規則。

推測規則採用 JSON 結構的形式,用於確定瀏覽器應預取或預渲染哪些資源。這是 推測規則 API 的一部分。

注意:推測規則可以在 Speculation-Rules HTTP 標頭引用的外部文字檔案中定義,使用下面提供的相同 JSON 表示形式。在開發人員無法直接修改文件本身的情況下,指定 HTTP 標頭很有用。

語法

html

<script type="speculationrules">
  // JSON object defining rules
</script>

注意: srcasyncnomoduledefercrossoriginintegrityreferrerpolicy 屬性不得指定。

異常

TypeError

推測規則定義不是有效的 JSON 物件。

描述

<script type="speculationrules"> 元素必須包含一個有效的 JSON 結構,用於定義推測規則。以下示例分別顯示了預取和預渲染規則

html

<script type="speculationrules">
  {
    "prefetch": [
      {
        "urls": ["next.html", "next2.html"],
        "requires": ["anonymous-client-ip-when-cross-origin"],
        "referrer_policy": "no-referrer"
      }
    ]
  }
</script>
html

<script type="speculationrules">
  {
    "prerender": [
      {
        "where": { "href_matches": "/next" },
        "eagerness": "eager"
      }
    ]
  }
</script>

推測規則 JSON 表示

JSON 結構在頂層包含一個或多個欄位,每個欄位代表一個定義推測規則的操作。目前支援的操作包括

"prefetch" 可選 實驗性

針對未來可能發生的導航的規則,這些導航應該下載其關聯的文件響應正文,從而在導航到這些文件時顯著提高效能。請注意,頁面引用的任何子資源都不會被下載。

"prerender" 可選 實驗性

針對未來可能發生的導航的規則,這些導航應該完全下載、渲染並載入其關聯的文件到一個不可見的選項卡中。這包括載入所有子資源,執行所有 JavaScript,甚至載入由 JavaScript 啟動的子資源並執行資料獲取。當導航到這些文件時,導航將是即時的,從而帶來重大的效能提升。

注意: 請查閱 推測規則 API 主頁,瞭解如何有效地使用預取和預渲染的完整詳細資訊。

每個操作欄位都包含一個數組,該陣列又包含一個或多個物件。每個物件包含一個定義一組 URL 和相關引數的規則。

每個物件可以包含以下屬性

"source"

一個字串,指示規則適用的 URL 的來源。這是可選的,因為該值始終可以從其他屬性推斷出來。

這可以是以下之一

"document"

指定 URL 將從關聯文件中的導航連結匹配(如 <a><area> 元素中定義),基於 "where" 鍵描述的條件。請注意,"where" 鍵的存在意味著 "source": "document",因此它是可選的。

"list"

指定 URL 將來自一個列表,該列表在 "urls" 鍵中指定。請注意,"urls" 鍵的存在意味著 "source": "list",因此它是可選的。

"urls" 實驗性

一個字串陣列,表示要將規則應用到的 URL 列表。這些可以是絕對 URL 或相對 URL。相對 URL 將相對於文件基本 URL(如果在文件中內聯)或相對於外部資源 URL(如果外部獲取)進行解析。"urls""where" 不能在同一規則中同時設定。

"where" 實驗性

一個物件,表示規則匹配關聯文件中包含的 URL 的條件。有效地,"where" 物件表示對頁面上的每個連結執行的測試,以檢視是否將推測規則應用於它。"where""urls" 不能在同一規則中同時設定。

此物件可以包含以下屬性之一

"href_matches"

一個包含 URL 模式的字串,或一個包含多個 URL 模式字串的陣列,這些字串遵循標準的 URL 模式 API 語法。文件中 URL 與模式匹配的連結將應用規則。

"relative_to"

"href_matches" 條件的情況下,這可以指定您希望該條件相對於哪個位置進行匹配。它的工作方式與 規則級別的 "relative_to" 完全相同,只是它僅影響 "where" 鍵內單個 "href_matches" 條件。

"selector_matches"

一個包含 CSS 選擇器 的字串,或一個包含多個 CSS 選擇器的陣列。由這些選擇器匹配的文件中的連結將應用規則。

"and"

一個數組,包含一個或多個包含條件("href_matches""selector_matches""and""not""or")的物件,所有這些條件都必須匹配才能將規則應用於它們。

"not"

一個包含一個條件("href_matches""selector_matches""and""not""or")的物件,如果它匹配,則不會將規則應用於它。所有匹配該條件的連結應用規則。

"or"

一個數組,包含一個或多個包含條件("href_matches""selector_matches""and""not""or")的物件,其中任何一個都可以匹配才能將規則應用於它們。

"where" 條件可以巢狀多層以建立複雜條件,或者您可以選擇將它們拆分為單獨的規則以保持簡單。有關更多說明和多個使用示例,請參閱 where 示例

"eagerness" 實驗性

一個字串,向瀏覽器提供一個提示,指示它應該多快地預取/預渲染連結目標,以便在效能優勢和資源開銷之間取得平衡。可能的取值包括

"immediate"

作者認為該連結很可能被點選,並且/或者文件可能需要大量時間來獲取。預取/預渲染應該儘快開始,僅受使用者偏好和資源限制等因素的約束。

"eager"

作者希望儘快預取/預渲染大量導航。當有任何輕微的跡象表明連結可能會被點選時,都應啟動預取/預渲染。例如,使用者可以將滑鼠游標移到連結上,將滑鼠懸停/聚焦一段時間,或者在連結位於顯眼位置時暫停滾動。

"moderate"

作者正在尋找 eagerconservative 之間的平衡點。當有合理的跡象表明使用者將在不久的將來點選連結時,應啟動預取/預渲染。例如,使用者可以將連結滾動到視口並將其懸停/聚焦一段時間。

"conservative"

作者希望從推測載入中獲得一些好處,同時以相當少的資源為代價。僅當用戶開始點選連結時才應啟動預取/預渲染,例如在 mousedownpointerdown 上。

如果未顯式指定 "eagerness",則列表 ("urls") 規則預設為 immediate,文件 ("where") 規則預設為 conservative。瀏覽器會將此提示與自身的啟發式方法結合考慮,因此如果不太積極的候選者被認為是更好的選擇,它可能會選擇作者提示為不太積極的連結。

一個字串,向瀏覽器提供一個提示,指示對於它正在接收預取/預渲染請求的文件,將設定什麼 No-Vary-Search 標頭值。瀏覽器可以使用它來提前確定是等待現有的預取/預渲染完成更有用,還是在推測規則匹配時啟動新的獲取請求。有關如何使用此功能的更多說明,請參閱 "expects_no_vary_search" 示例

"referrer_policy" 實驗性

一個字串,表示在請求規則中指定的 URL 時要使用的特定推薦人策略字串 - 請參閱 Referrer-Policy 以瞭解可能的取值。這樣做的目的是允許引用頁面為推測請求設定比頁面已設定的策略(預設情況下或使用 Referrer-Policy)更嚴格的策略。

注意: 跨站點預取需要一個推薦人策略,該策略至少與預設的 "strict-origin-when-cross-origin" 值一樣嚴格 - 因此為 "strict-origin-when-cross-origin""same-origin""strict-origin""no-referrer"。只要推測規則中設定的較寬鬆的策略仍然足夠嚴格以滿足跨站點情況,它就會覆蓋引用頁面上設定的更嚴格的策略。

注意: 在文件規則的情況下,將使用匹配的連結指定的推薦人策略(例如,使用 referrerpolicy 屬性),除非規則指定覆蓋它的策略。

"relative_to" 實驗性

一個字串,指定您希望透過 URL 匹配的連結相對於哪個位置進行匹配。該值可以是以下之一

document

URL 應相對於設定推測規則的文件進行匹配。

ruleset

URL 應相對於指定規則的檔案進行匹配。這是預設值。

此鍵設定僅與在外部檔案中定義的規則相關(使用 Speculation-Rules 標頭設定)。當在與設定它們的同一個文件中指定規則時(即在內聯 <script> 元素中),它沒有任何區別。

"requires" 實驗性

一個字串陣列,表示解析規則的瀏覽器的功能,如果要將規則應用於指定的 URL,則必須具備這些功能。

警告: 即使瀏覽器支援 推測規則 API,如果無法滿足指定的任何要求,預取也將自動失敗。

可能的取值包括

"anonymous-client-ip-when-cross-origin"

(僅限預取)指定規則僅在使用者代理可以防止客戶端 IP 地址在發出跨源預取請求時對源伺服器可見時才匹配。其工作原理取決於瀏覽器實現的具體細節。例如

  • Chrome 的實現使用 Google 擁有的代理隱藏 IP 地址,因此預設情況下,它僅適用於 Google 控制的推薦人(因為在這種情況下,將目標的 URL 傳送給 Google 不會造成額外的隱私洩露)。當在非 Google 擁有的網站上使用時,包含此規則的規則僅適用於在 chrome://settings/preloading 中開啟“增強型預載入”的使用者。
  • 其他基於 Chromium 的瀏覽器將需要提供自己的解決方案。建議在所有目標瀏覽器中進行徹底的測試。
  • 未來的 Safari 實現可能會使用類似於 iCloud 私人中繼 的東西。
  • 未來的 Firefox 實現可能會使用基於 Mozilla VPN 產品的東西。

注意:由於推測規則使用<script>元素,如果站點包含該元素,則需要在Content-Security-Policy script-src指令中顯式允許。這可以透過新增"inline-speculation-rules"值以及雜湊或nonce源來實現。

示例

在同一組規則中使用預取和預渲染

描述部分顯示的基本示例包含為預取和預渲染定義的單獨推測規則。可以在一組規則中定義兩者。

html

<script type="speculationrules">
  {
    "prefetch": [
      {
        "urls": ["next.html", "next2.html"],
        "requires": ["anonymous-client-ip-when-cross-origin"],
        "referrer_policy": "no-referrer"
      }
    ],
    "prerender": [
      {
        "where": { "selector_matches": ".product-link" },
        "eagerness": "eager"
      }
    ]
  }
</script>

注意:此程式碼片段提供了一個列表("urls")規則和一個文件("where")規則示例。

多組規則

也可以在一個HTML檔案中包含多組規則。

html

<script type="speculationrules">
  {
    "prefetch": [
      {
        "urls": ["next.html", "next2.html"],
        "requires": ["anonymous-client-ip-when-cross-origin"],
        "referrer_policy": "no-referrer"
      }
    ]
  }
</script>
<script type="speculationrules">
  {
    "prerender": [
      {
        "where": { "selector_matches": ".product-link" },
        "eagerness": "eager"
      }
    ]
  }
</script>

以及在一組結果中包含多個規則。

js
<script type="speculationrules">
{
  "prerender": [
    {
      "urls": ["one.html"]
    },
    {
      "urls": ["two.html"]
    }
  ]
}
</script>

動態插入規則

下面是一個示例,它檢測推測規則的功能,如果支援,則透過JavaScript動態新增預渲染推測規則。

js
if (
  HTMLScriptElement.supports &&
  HTMLScriptElement.supports("speculationrules")
) {
  const specScript = document.createElement("script");
  specScript.type = "speculationrules";
  const specRules = {
    prerender: [
      {
        urls: ["/next.html"],
      },
    ],
  };
  specScript.textContent = JSON.stringify(specRules);
  console.log("added speculation rules to: next.html");
  document.body.append(specScript);
}

您可以在此預渲染演示頁面中檢視其操作。

where語法示例

基於文件的規則包含一個"where"屬性,該屬性是一個包含定義匹配文件中哪些連結的條件的物件。實際上,"where"物件表示對頁面上的每個連結執行的測試,以檢視是否將推測規則應用於它。

最基本的版本將匹配單個URL模式或CSS選擇器。

json
{ "where": { "href_matches": "/next" } }
json
{ "where": { "selector_matches": ".important-link" } }

"href_matches""selector_matches"也可以設定為一個值陣列,以便可以同時匹配多個URL模式或CSS選擇器。

json
{ "where": { "href_matches": ["/next", "/profile"] } }
json
{ "where": { "selector_matches": [".important-link", "#unique-link"] } }

URL模式和選擇器也可以包含萬用字元(*)字元,允許單個值匹配多個URL。例如,下面的物件可以匹配user/user/settingsuser/stats等。

json
{ "where": { "href_matches": "/user/*" } }

搜尋引數(或查詢字串)也可以在href_matches中進行定位。例如,下面的物件可以匹配所有具有category搜尋引數(作為第一個或後續引數)的同源URL。

json
{ "where": { "href_matches": "/*\\?*(^|&)category=*" } }

任何條件都可以透過將其放在"not"條件內來否定——這意味著,當匹配時,連結不會應用推測規則,但當匹配時,應用。以下示例將導致所有匹配URL模式/logout的連結應用規則,但不匹配/logout的連結。

json
{ "where": { "not": { "href_matches": "/logout" } } }

使用"and""or"組合多個"where"條件

可以在"and""or"條件內組合多個條件——這些條件的值為包含多個條件的陣列,所有或任何一個(分別)必須匹配才能將推測規則應用於連結。使用"and""or",條件可以巢狀多層——沒有指定允許的巢狀層數限制。

"where"物件視為等效於if語句很有用。所以

{ and: [A, B, { or: [C, { not: D }] }] }

等效於

if (A && B && (C || !D)) {
  apply speculation rule
}

在以下完整的推測規則示例中,所有同源頁面都標記為預取,除了已知存在問題的頁面——/logout頁面和標記為.no-prerender類的任何連結。

html

<script type="speculationrules">
  {
    "prefetch": [
      {
        "where": {
          "and": [
            { "href_matches": "/*" },
            { "not": { "href_matches": "/logout" } },
            { "not": { "selector_matches": ".no-prerender" } }
          ]
        }
      }
    ]
  }
</script>

注意:上面的where模式不包含跨站點連結,跨站點連結支援預取(前提是使用者未為目標站點設定任何cookie,以防止跟蹤),但不支援預渲染。

"relative_to"示例

對於外部獲取的規則集(即透過Speculation-Rules響應頭),列表規則中的URL和文件規則中的URL模式預設情況下相對於包含的外部文字檔案的URL進行解析。要相對於文件的基本URL解析列表規則中的URL,請使用"relative_to",如下所示。

json
{
  "urls": ["/home", "/about"],
  "relative_to": "document"
}

對於文件規則,"relative_to"可以直接與"href_matches"配對,並且文件的基本URL僅用於該特定條件中的模式。

json
{
  "where": {
    "or": [
      { "href_matches": "/home", "relative_to": "document" },
      { "href_matches": "/about" }
    ]
  }
}

在上面的示例中,只有第一個"href_matches"將相對於文件的基本URL進行匹配。

relative_to主要與推測規則JSON檔案與您希望將其應用到的文件位於不同的來源時相關。

  1. 如果文件位於https://example.com/some/subpage.html,規則位於https://example.com/resources/rules.json,則/home始終等於https://example.com/home,無論relative_to是否設定為documentruleset
  2. 但是,如果文件位於https://example.com/some/subpage.html,規則位於https://other.example/resources/rules.json(例如,在第三方或無cookie資源來源上),則
    • "relative_to": "document"將導致/home等於https://example.com/home
    • "relative_to": "ruleset"將導致/home等於https://other.example/home
    這是"relative_to"的典型用例。
  3. 另一個潛在的(但更罕見的)用例是當您的URL以home而不是/home的形式指定時。如果文件位於https://example.com/some/subpage.html,規則位於https://example.com/resources/rules.json,則
    • "relative_to": "document"將導致home等於https://example.com/some/home
    • "relative_to": "ruleset"將導致home等於https://example.com/resources/home

"expects_no_vary_search"示例

考慮使用者目錄登入頁面/users的情況,該頁面添加了一個id引數以顯示特定使用者資訊,例如/users?id=345。對於快取目的,是否應將此URL視為相同取決於應用程式的行為。

  1. 如果此引數會導致載入一個包含指定使用者資訊的全新頁面,則應分別快取該URL。
  2. 如果此引數會導致在同一頁面上突出顯示指定的使用者資訊,並可能顯示一個顯示其資料的抽屜面板,則應將該URL視為快取目的相同。這可能會導致使用者頁面載入方面的效能改進,並且可以透過No-Vary-Search實現,其值為params=("id")

這如何影響推測規則?考慮以下程式碼

html

<script type="speculationrules">
  {
    "prefetch": [
      {
        "urls": ["/users"]
      }
    ]
  }
</script>
<a href="/users?id=345">User Bob</a>

在這種情況下,當用戶開始導航到/users?id=345時,而/users的預取標頭尚未收到時會發生什麼?此時,瀏覽器不知道No-Vary-Search值(如果有)將是什麼。如果沒有設定No-Vary-Search值,並且應用程式行為更像上面的選項1,則預取將被浪費,瀏覽器需要從頭開始獲取單獨的/users?id=345頁面。

為了解決這個問題,我們可以提供頁面作者期望的No-Vary-Search值的提示。推測規則可以有一個"expects_no_vary_search"欄位,其中包含預期標頭值的字串表示形式。

html

<script type="speculationrules">
  {
    "prefetch": [
      {
        "urls": ["/users"],
        "expects_no_vary_search": "params=(\"id\")"
      }
    ]
  }
</script>
<a href="/users?id=345">User Bob</a>

這表示上面描述的選項2是伺服器預期產生的結果。如果在正在進行/users的預取時開始導航,這會通知瀏覽器等待預取,而不是立即開始對/users?id=345的另一個獲取。

文件規則也可以與"expects_no_vary_search"結合使用,具體取決於使用的模式。例如,在以下情況下

html

<script type="speculationrules">
  {
    "prefetch": [
      {
        { "where": { "href_matches": "/users?id=*" } },
        "expects_no_vary_search": "params=(\"id\")"
      }
    ]
  }
</script>
<a href="/users?id=012">User Bill</a>
<a href="/users?id=345">User Bob</a>
<a href="/users?id=678">User Ben</a>

如果將滑鼠懸停在連結上,瀏覽器將開始預取該特定連結。

如果使用者在預取完成之前將滑鼠懸停在另一個連結上,則expects_no_vary_search模式會告訴瀏覽器無需取消當前預取,因為對於此上下文(以及快取目的),所有具有idURL引數值的/usersURL實際上都指向同一頁面。

eagerness示例

以下文件規則集顯示瞭如何使用eagerness來提示瀏覽器預渲染每個匹配的連結集的積極性。

html

<script type="speculationrules">
  {
    "prerender": [
      {
        "where": { "href_matches": "/*" },
        "eagerness": "conservative"
      },
      {
        "where": { "selector_matches": ".product-link" },
        "eagerness": "eager"
      }
    ]
  }
</script>

這裡我們暗示

  • 文件中包含的所有同站點連結都應保守地預渲染(即,當用戶開始啟用它們時)。
  • 文件中的任何產品連結(在本例中,具有class.product-link的連結)都應積極地預渲染(即,如果使用者進行任何型別的導航操作)。

注意:積極性設定的效果對列表規則不太有用。預設情況下,列表規則URL會在解析規則後立即預取/預渲染,這正是您所期望的——它們旨在顯式列出您希望儘快提供的優先順序高的URL。因此,在當前實現中,eagerimmediate具有相同的效果。較低的積極性設定用於在與連結互動時進行預取/預渲染,並且對於這些設定,您更有可能使用文件規則在頁面上找到它們。

規範

規範
推測規則
# speculation-rules-script

瀏覽器相容性

BCD 表格僅在啟用 JavaScript 的瀏覽器中載入。

另請參閱