NoState 预提取简介

Katie Hempenius
Katie Hempenius

简介

NoState 预渲染是 Chrome 中的一种新机制,可替代已弃用的预渲染流程,用于支持 <link rel="prerender"> 等功能。与预渲染一样,它会预先提取资源;但与预渲染不同的是,它不会预先执行 JavaScript 或渲染网页的任何部分。NoState 预提取的目标是使用比预渲染更少的内存,同时仍缩短网页加载时间。

NoState 预提取不是 API,而是 Chrome 用来实现各种 API 和功能的一种机制。Resource Hints API 以及通过 Chrome 地址栏预提取页面都是使用 NoState 预提取实现的。如果您使用的是 Chrome 63 或更高版本,您的浏览器已经在使用 NoState Prefetch 实现 <link rel="prerender"> 等功能。

本文介绍了 NoStatePrefetch 的工作原理、引入它的动机,并说明了如何使用 Chrome 的直方图查看有关其使用情况的统计信息。

设计初衷

引入 NoState 预提取主要有以下两个动机:

减少内存用量

NoState 预提取仅使用约 45MiB 的内存。维护预加载扫描程序是 NoState 预提取的主要内存开销,在不同用例中,此开销保持相对稳定。增加提取大小或提取量对 NoState 预提取消耗的内存量不会产生显著影响。

相比之下,预渲染通常消耗 100MiB 的内存,内存消耗上限为 150MiB。这种高内存消耗使其不适合低端(即 RAM 小于 512MB)的设备。因此,Chrome 不会在低端设备上进行预渲染,而是预连接

为新的 Web 平台功能提供支持

通过预渲染,不应面向用户(例如播放音乐或视频)或执行有状态的操作(例如更改会话或本地存储空间)。不过,阻止在呈现网页时执行这些操作可能既困难又复杂。NoState 预提取只会提前提取资源,而不会执行代码或呈现网页。这样可以更轻松地防止发生面向用户的有状态操作。

实现

以下步骤介绍了 NoState 预提取的工作原理。

  1. 触发了 NoStatePrefetch

    如果满足以下两个条件,预渲染资源提示(即 <link rel="prerender">)和某些 Chrome 功能将会触发 NoState 预提取:a) 用户未使用低端设备;b) 用户未使用移动网络。

  2. 为 NoState 预提取创建了新的专用渲染程序。

    在 Chrome 中,“渲染程序”负责获取、解析该文档、构建其渲染树并将结果绘制到屏幕上。Chrome 中的每个标签页以及每个 NoState 预提取进程都有自己的渲染程序来隔离应用。这有助于最大限度地降低出现问题(例如标签页崩溃)造成的影响,并防止恶意代码访问其他标签页或系统的其他部分。

  3. 系统会提取通过 NoState 预提取功能加载的资源。然后,HTMLPreloadScanner 会扫描该资源,以发现需要提取的任何子资源。 如果主要资源或其任何子资源具有已注册的 Service Worker,则这些请求将会通过相应的 Service Worker。

    NoState 预提取仅支持 GET HTTP 方法;它不会提取任何需要使用其他 HTTP 方法的子资源。此外,它也不会提取任何需要用户操作的资源(例如,身份验证弹出式窗口、SSL 客户端证书或手动替换)。

  4. 提取的子资源将以“IDLE”网络优先级进行提取。

    “IDLE”网络优先级是 Chrome 中可能的最低网络优先级。

  5. NoState 预提取检索到的所有资源根据其缓存标头进行缓存。

    NoState 预提取将缓存除带有 no-store Cache-Control 标头的资源之外的所有资源。如果存在 Vary 响应标头、no-cache Cache-Control 标头,或者资源的存在时间超过 5 分钟,系统会在使用前重新验证资源。

  6. 加载所有子资源后,渲染程序被终止。

    如果子资源超时,渲染程序将在 30 秒后终止。

  7. 除了更新 Cookie 存储区和本地 DNS 缓存之外,浏览器不会进行任何状态修改。 请务必指出这一点,因为这是“NoState Prefetch”中的“NoState”。

    此时,在“正常”网页加载过程中,浏览器可能会执行一些会修改浏览器状态的操作:例如执行 JavaScript、更改 sessionStoragelocalStorage、播放音乐或视频、使用 History API,或提示用户。NoState 预提取中只会发生状态修改,包括在响应到达时更新 DNS 缓存,以及如果响应包含 Set-Cookie 标头,则更新 Cookie 存储区。

  8. 当需要资源时,系统会将其加载到浏览器窗口中。

    不过,与预渲染的网页不同,网页不会立即显示,仍然需要由浏览器呈现。浏览器不会重复使用它用于 NoState 预提取的渲染程序,而是改用新的渲染程序。不提前渲染页面可以减少 NoStatePrefetch 的内存消耗,但也会降低可能对页面加载时间产生的影响。

    如果页面具有 Service Worker,则此次页面加载将再次通过 Service Worker。

    如果 NoState 预提取在需要页面时未完成子资源的提取,浏览器将继续从 NoState 预提取停止的位置继续页面加载过程。浏览器仍然需要提取资源,但与未启动 NoState 预提取所需的资源一样多。

对网站分析的影响

使用 NoState 预提取加载的网页由网络分析工具注册的时间略有不同,具体取决于该工具是在客户端还是服务器端收集数据。

客户端分析脚本会在网页显示给用户时记录一次网页浏览。这些脚本依赖于执行 JavaScript,而 NoState Prefetch 不执行任何 JavaScript。

服务器端分析工具会在处理请求时注册指标。对于通过 NoState 预提取加载的资源,从处理请求到客户端实际使用响应(如果确实使用了响应)之间可能存在明显的时间差。从 Chrome 69 开始,NoState Prefetch 会向所有请求添加标头 Purpose: Prefetch,以便与常规浏览区分开来。

去看看

2017 年 12 月,Chrome 63 中推出了 NoStatePrefetch。它目前用于:

  • 实现 prerender 资源提示
  • 提取 Google 搜索结果中的第一个结果
  • 抓取 Chrome 地址栏预测接下来可能会访问的网页

您可以通过 Chrome Internals 查看 NoStatePrefetch 的使用情况。

如需查看已通过 NoState Prefetch 加载的网站的列表,请转到 chrome://net-internals/#prerender

如需查看您的 NoState 预提取使用情况的统计信息,请前往 chrome://影集并搜索“NoStatePrefetch”。有三种不同的 NoState 预提取直方图,分别与 NoState 预提取的使用情形分别对应:

  • “NoStatePrefetch”(预渲染资源提示的使用情况统计信息)
  • “gws_NoStatePrefetch”(Google 搜索结果页的使用情况统计信息)
  • “omnibox_NoStatePrefetch”(Chrome 地址栏的使用情况统计信息)