diff --git a/files/zh-cn/web/performance/speculative_loading/index.md b/files/zh-cn/web/performance/speculative_loading/index.md new file mode 100644 index 00000000000000..c7b9f5a1a467b5 --- /dev/null +++ b/files/zh-cn/web/performance/speculative_loading/index.md @@ -0,0 +1,185 @@ +--- +title: 推测性加载 +slug: Web/Performance/Speculative_loading +page-type: guide +--- + +{{QuickLinksWithSubPages("Web/Performance")}} + +**推测性加载**是指在用户实际访问相关页面之前,基于推测用户最有可能访问的页面,进行导航操作(如 DNS 获取、获取资源或渲染文档)的行为。 + +这些推测可以由开发者提供(例如他们网站上最受欢迎的目的地列表),或者由浏览器启发式确定(例如基于用户历史记录中的热门网站)。当成功使用时,这些技术可以让页面更快地可用或在某些情况下立即可用,以显著提高性能。 + +本页面总结了可用的推测性加载技术,以及何时可以使用和应该使用这些技术来提高性能。 + +## 推测性加载机制 + +推测性加载有几种机制: + +- **预加载(Prefetching)** 在需要之前获取渲染文档(或文档的一部分)所需的一些或全部资源,以便在将要渲染时更快地实现渲染。 +- **预渲染(Prerendering)** 更进一步,会实际渲染内容,以便在需要时可以展示。根据实现方式的不同,可以实现从旧页面到新页面的即时导航。 +- **预连接(Preconnecting)** 通过预先执行部分或全部的连接握手(即 DNS + TCP + TLS)来加速来自给定源的未来加载。 + +> [!NOTE] +> 上述描述是高层次和泛化的。浏览器究竟将执行何种操作来实现预加载和预渲染,取决于所使用的功能。更准确的功能描述在下面的[推测性加载功能](#speculative_loading_features)部分给出。 + +## 推测性加载是如何实现的? + +推测性加载主要通过两种方式实现。 + +首先,一些浏览器会根据各种启发式方法自动预渲染页面,以提供自动的性能改进。具体如何实现取决于浏览器的实现。例如,Chrome 会在地址栏中输入匹配字符串时自动预渲染页面——如果它有很高的信心你会访问该页面(有关详细信息,请参阅[查看 Chrome 的地址栏推测](https://developer.chrome.google.cn/docs/web-platform/prerender-pages#view_chromes_address_bar_predictions))。此外,当搜索词输入到地址栏时,它可能会自动预渲染搜索结果页面,当搜索引擎指示这样做时。它使用与 [Speculation Rules API](/zh-CN/docs/Web/API/Speculation_Rules_API) 相同的机制来实现这一点。 + +其次,有几个不同的平台功能可供开发者使用,以提供他们希望浏览器执行的推测性加载的指令。这些功能将在下一节中进行描述。 + +## 推测性加载功能 + +### `` + +[``](/zh-CN/docs/Web/HTML/Attributes/rel/preconnect) 给浏览器一个提示,表明用户可能需要来自指定源的资源,因此浏览器可以通过预先启动对该源的连接来提高性能。支持的浏览器将预先执行部分或全部连接握手(即 DNS + TCP + TLS)。 + +例如: + +```html + +``` + +``在浏览器中得到广泛支持,并将为任何未来的跨源 HTTP 请求、导航或子资源提供好处。对于同源请求没有好处,因为连接已经打开。 + +如果页面需要连接到许多第三方域,全部预连接可能会适得其反。`` 提示最好仅用于最关键的连接。对于其他的连接,只需使用 `` 来节省第一步的时间——DNS 查找。 + +你还可以将预连接实现为 HTTP [Link](/zh-CN/docs/Web/HTTP/Headers/Link) 标头,例如: + +```http +Link: ; rel="preconnect" +``` + +### `` + +[``](/zh-CN/docs/Web/HTML/Attributes/rel/dns-prefetch) 给浏览器一个提示,表明用户可能需要来自指定源的资源,因此浏览器可以通过预先为该源执行 DNS 解析来提高性能。它与 `` 相同,只是它只处理 DNS 部分。 + +同样,浏览器广泛支持此功能,另外这对于同源请求并没有收益,因为连接已经打开过了。 + +例如: + +```html + +``` + +> [!NOTE] +> 有关详细信息,请参阅[使用 dns-prefetch](/zh-CN/docs/Web/Performance/dns-prefetch)。 + +### `` + +[``](/zh-CN/docs/Web/HTML/Attributes/rel/preload) 给浏览器一个提示,表明哪些资源在 _当前页面_ 上是高优先级的,因此浏览器可以在看到 {{htmlelement("link")}} 元素时尽早开始下载它们。 + +例如: + +```html + + + +``` + +结果保存在每个文档的内存缓存中。如果你预加载当前页面不使用的资源,通常会造成一种资源浪费,尽管结果可能会填充 HTTP 缓存(如果标头允许)。 + +你还可以将预加载实现为 HTTP [Link](/zh-CN/docs/Web/HTTP/Headers/Link) 标头,例如: + +```http +Link: ; rel="preload" +``` + +现代浏览器普遍支持 ``/``。 + +### `` + +[``](/zh-CN/docs/Web/HTML/Attributes/rel/modulepreload) 给浏览器一个提示,表明哪些 JavaScript 模块在 _当前页面_ 上是高优先级的,因此浏览器可以在看到它们时尽早开始下载。 + +例如: + +```js + +``` + +它是 ``的专用版本,用于 [JavaScript 模块](/zh-CN/docs/Web/JavaScript/Guide/Modules),并且基本以相同的方式工作。然而还是有些区别: + +- 浏览器知道资源是一个 JavaScript 模块,因为不需要 `as` 属性,它可以使用正确的凭据模式来避免双重获取。 +- 浏览器不仅下载并将其存储在缓存中,还将其解析并编译到内存模块映射中。 +- 浏览器还可以自动为模块依赖项做同样的事情。 + +### `` + +[``](/zh-CN/docs/Web/HTML/Attributes/rel/prefetch) 给浏览器一个提示,表明用户可能需要目标资源进行未来的导航,因此浏览器可以通过预先获取和缓存资源来提高用户体验。`` 用于同站导航资源或同站页面使用的子资源。 + +例如: + +```js + +``` + +预加载可用于获取可能的下一次导航的 HTML 和子资源。一个常见的用例是简单的网站着陆页,该页获取整个站点其余部分使用的更“重量级”的资源。 + +```html + + +``` + +结果保存在磁盘中的 HTTP 缓存中。因此,即便它们不被当前页面使用,也对于预加载子资源很有用。你还可以使用它来预加载用户可能在站点上访问的下一个文档。然而,你也因此要小心地处理标头——例如某些 [Cache-Control](/zh-CN/docs/Web/HTTP/Headers/Cache-Control) 标头可能会阻止预加载(例如 `no-cache` 或 `no-store`)。 + +现在许多浏览器实现了一些形式的[缓存分区](https://developer.chrome.google.cn/blog/http-cache-partitioning?hl=zh-cn),这使得 `` 对于那些打算由不同顶级站点使用的资源无用。这包括会跨站点导航的主文档。例如下面的预加载: + +```html + +``` + +将无法从 `https://aggregator.example/` 访问。 + +> **注意:** `` 在功能上等同于一个带有 `priority: "low"` 选项的 {{domxref("Window/fetch", "fetch()")}} 调用,但前者通常具有更低的优先级,并且请求上会设置一个 [`Sec-Purpose: prefetch`](/zh-CN/docs/Web/HTTP/Headers/Sec-Purpose) 。 + +> [!NOTE] > `prefetch` 操作的获取请求将产生一个包含 HTTP 标头 [`Sec-Purpose: prefetch`](/zh-CN/docs/Web/HTTP/Headers/Sec-Purpose) 的 HTTP 请求。服务器可能会使用此标头更改资源的缓存超时时间或执行其他特殊处理。 +> 请求还将包括 {{HTTPHeader("Sec-Fetch-Dest")}} 标头,其值为 `empty`。 +> 请求中的 {{HTTPHeader("Accept")}} 标头将与正常导航请求中使用的值匹配。这允许浏览器在导航后找到匹配的缓存资源。 +> 如果返回响应,它将与请求一起缓存在 HTTP 缓存中。 + +### `` + +> [!NOTE] + +这项技术仅在 Chrome 中可用,现已弃用。作为取代,应该使用 [Speculation Rules API](/zh-CN/docs/Web/API/Speculation_Rules_API) 。 + +[``](/zh-CN/docs/Web/HTML/Attributes/rel/prerender) 给浏览器一个提示,表明用户可能需要目标资源进行下一次导航,因此浏览器可以通过预渲染资源来提高性能。`prerender` 仅用于同站导航,因此适用于多页应用程序(MPA),而不适用于单页应用程序(SPA)。 + +例如: + +```html + +``` + +它将获取所引用的文档,然后获取任何静态可寻的链接资源,将结果存储在磁盘中的 HTTP 缓存,超时时间为五分钟。通过 JavaScript 加载的子资源是例外情况——它无法找到这些资源。它还有其他问题——像 `` 一样,它也可能被 [Cache-Control](/zh-CN/docs/Web/HTTP/Headers/Cache-Control) 标头阻止,并因浏览器[缓存分区](https://developer.chrome.google.cn/blog/http-cache-partitioning)而对那些打算由不同顶级站点使用的资源无用。 + +### Speculation Rules API + +[Speculation Rules API](/zh-CN/docs/Web/API/Speculation_Rules_API) 用于指定一组规则,以确定浏览器应预加载或预渲染哪些未来文档。这些规则作为内联 `