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 地址栏的使用情况统计信息)