<script type="speculationrules">

可用性有限

此特性不是基线特性,因为它在一些最广泛使用的浏览器中不起作用。

实验性: 这是一项实验性技术
在生产中使用此技术之前,请仔细检查浏览器兼容性表格

<script> 元素的 type 属性的 speculationrules 值表示该元素的主体包含推测规则。

推测规则采用 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"

指定将根据 "where" 键描述的条件,从相关文档中的导航链接(如 <a><area> 元素中定义)匹配 URL。请注意,"where" 键的存在意味着 "source": "document",因此它是可选的。

"list"

指定 URL 将来自 "urls" 键中指定的列表。请注意,"urls" 键的存在意味着 "source": "list",因此它是可选的。

"urls" 实验性

一个字符串数组,表示要应用规则的 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"

一个数组,包含一个或多个包含条件的 JSON 对象("href_matches""selector_matches""and""not""or"),所有这些条件都必须匹配才能将规则应用于它们。

"not"

一个包含一个条件("href_matches""selector_matches""and""not""or")的对象,如果它匹配,则不会将规则应用于它。所有匹配条件的链接都将应用该规则。

"or"

一个数组,包含一个或多个包含条件的 JSON 对象("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。这样做的目的是允许引用页面专门为推测性请求设置比页面已设置的策略(默认或使用 Referrer-Policy)更严格的策略。

注意:跨站预取需要至少与默认 "strict-origin-when-cross-origin" 值一样严格的 referrer policy —— 即 "strict-origin-when-cross-origin""same-origin""strict-origin""no-referrer"。推测规则中设置的较宽松策略将覆盖引用页面上设置的较严格策略,只要它对跨站情况仍然足够严格。

注意:在文档规则的情况下,将使用匹配链接指定的 referrer policy(例如,使用 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 控制的 referrer(因为在这种情况下,将目标 URL 发送到 Google 不会造成额外的隐私泄露)。在非 Google 拥有的网站上使用时,包含此项的规则仅适用于在 chrome://settings/preloading 中打开“增强预加载”的用户。
  • 其他基于 Chromium 的浏览器将不得不提供自己的解决方案。建议在所有目标浏览器中进行彻底测试。
  • 未来的 Safari 实现可能使用类似 iCloud 私密中继 的东西。
  • 未来的 Firefox 实现可能使用基于 Mozilla VPN 产品的东西。
"tag" 实验性

一个字符串,用于标识规则或规则集。这将包含在任何受该规则覆盖的推测的 Sec-Speculation-Tags 请求头中。

"target_hint" 实验性

一个字符串,指示页面期望预渲染内容被激活的位置。此指令不支持预取推测。允许的值是

"target_hint": "_blank"

在新页面中打开重新渲染的内容。

"target_hint": "_self"

在当前页面中打开重新渲染的内容。如果未指定,这是默认值。

注意:由于推测规则使用 <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>

以及单个结果集中的多个规则

html
<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 进行匹配。

如果推测规则 JSON 文件与您希望应用它们的文档位于不同的来源,则 relative_to 主要相关

  1. 如果文档位于 https://example.com/some/subpage.html 并且规则位于 https://example.com/resources/rules.json,则无论 relative_to 设置为 document 还是 ruleset/home 始终等同于 https://example.com/home

  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 模式会告诉浏览器无需取消当前的预取,因为所有具有 id URL 参数值的 /users URL 在此上下文中(并出于缓存目的)有效地指向同一页面。

警告:将预渲染与 No-Vary-Search 一起使用时必须格外小心,因为页面最初可能使用不同的 URL 参数进行预渲染。No-Vary-Search 用于从服务器提供相同资源但客户端出于各种原因(客户端渲染、用于分析测量的 UTM 参数等)使用的 URL 参数。由于初始预渲染可能用于不同的 URL 参数,任何依赖它们的代码都应仅在预渲染激活后运行。

可以在空格分隔的数组中提供多个参数

html
<script type="speculationrules">
  {
    "prefetch": [
      {
        { "where": { "href_matches": "/users?id=*" } },
        "expects_no_vary_search": "params=(\"id\" \"order\" \"lang\")"
      }
    ]
  }
</script>

注意:作为 结构化字段,参数应为空格分隔的带引号字符串——如上所示——而不是逗号分隔的,开发人员可能更习惯于此。

eagerness 示例

以下一组文档规则显示了如何使用 eagerness 来提示浏览器预渲染每个匹配链接集的积极性。

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

在这里,我们提示

  • 文档中包含的所有同站链接都应保守地预渲染(即,当用户开始激活它们时)。
  • 文档中的任何产品链接(在本例中,具有 .product-link 类的链接)都应积极地预渲染(即,如果用户做出任何导航到它们的动作)。

注意:eagerness 设置对列表规则的作用较小。默认情况下,列表规则 URL 在解析规则后会立即预取/预渲染,这正是您所期望的——它们旨在明确列出您希望尽快可用的高优先级 URL。因此,在当前实现中,eagerimmediate 具有相同的效果。较低的 eagerness 设置用于在链接交互时进行预取/预渲染,对于这些情况,您更可能使用文档规则在页面上查找它们。

tag 示例

tag 可以包含在顶层,以标识整个规则集

html
<script type="speculationrules">
  {
    "tag": "my-rules",
    "prerender": [
      {
        "where": { "href_matches": "/*" },
        "eagerness": "conservative"
      }
    ]
  }
</script>

或识别单个规则

html
<script type="speculationrules">
  {
    "prefetch": [
      "tag": "my-prefetch-rule",
      "urls": ["next.html"]
    ],
    "prerender": [
      "tag": "my-prerender-rule",
      "urls": ["next2.html"]
    ],
  }
</script>

有关更多示例,请参阅 Sec-Speculation-Tags

target_hint 示例

可以包含 target_hint 以指示将在其中打开匹配的预渲染推测的目标窗口

html
<script type="speculationrules">
  {
    "tag": "my-rules",
    "prerender": [
      {
        "eagerness": "eager",
        "target_hint": "_blank",
        "urls": ["page2.html"]
      }
    ]
  }
</script>

上面的规则允许以下链接在适当的目标中正确预渲染

html
<a href="page1.html">Open link in this window</a>
<a target="_blank" href="page2.html">Open link in new window</a>

target_hint 仅适用于使用 urls 的列表规则。对于文档规则(使用 where)则不需要,因为在这些规则中,目标可以从 <a> 链接元素的 target 属性中得知。

规范

规范
HTML
# 推测性加载

浏览器兼容性

另见