<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 的浏览器中加载。

另请参阅