通过投机性预渲染为浏览器带来即时的页面加载 2021-11-01 默认分类 暂无评论 1667 次阅读 ![NDg4DvtC6Hkbly4MyGkZ.jpeg][1] 资源提示,如preconnect、preload、prefetch和prerender,帮助浏览器找出用户在不久的将来会需要哪些资源。 preconnect和preload是声明性的提示--浏览器必须对它们采取行动,所以当你确定在下一次加载时需要某个资源时,就使用它们。 prefetch和prerender是推测性提示--用它们来建议浏览器获取某种资源,因为它很有可能被需要。 本文重点介绍投机性预取和预渲染。了解更多关于它们的使用方法,当前实现的缺点,以及实现复杂推测的流行外部库。为浏览器带来同源推测性预渲染的增强功能正在开发中,您可以了解更多关于它们的设计,并参与Chrome origin的试用。 **prefetch和prerender。目前的实现方式 ** -------------------------------- 用户在查看与其兴趣相关的链接列表(例如,与搜索关键词或用户偏好相匹配的产品或文章列表)时,可能会点击顶部的链接。如果他们导航回到列表页,他们可能会点击列表中的下一个链接。预取和预渲染依赖于对用户行为的这种了解。开发人员推测哪个页面(B)有可能在特定页面(A)之后被请求。 **预取提示** -------- 当开发者在A页中加入一个预取提示,告诉浏览器可以提前获取B页或B页中的特定资源时,浏览器就可以在闲置时获取这些资源,而不影响A页的处理。 在起始页(我们例子中的A页)使用预取的语法如下 ``` ``` 这里的as属性是可选的,但可以帮助浏览器设置正确的标题,以确定该资源是否已经在缓存中。 在过去的几年中,对预取的支持和实施方案已经略微成熟。[浏览器支持][2] **prerender hint** ------------------ 包括一个prerender提示,告诉浏览器要提前渲染B页。当用户实际点击B页的链接时,预渲染页面可以实现即时的导航体验。 在原生页中使用prerender的语法如下 ``` ``` **预取的实施** --------- 关于预取行为,有几个要点需要注意(尤其是在Chrome): - 你可以完全预取下一个页面,也可以预取同源的子资源,比如下一个页面需要的样式表或脚本。 - 预取的资源如果是可缓存的,就会存储在HTTP缓存中。 - Chrome会将缓存项目保留5分钟。 - 当资源被请求或需要时,它们会从缓存中被检索出来。然而,如果它们还没有完成加载,部分加载的资源就会被Chrome捡起来继续加载。 - 预取资源会消耗额外的字节,如果用户启用了数据保护模式,则不建议使用。连接类型和其他关于用户数据偏好的细节可以通过网络信息API确定。 **使用无状态预取的prerender实现方式** ------------------------- 在Chromium中,最初的prerender提示的实现使用了大量的内存,所以它被废弃了,转而使用无状态预取,提前获取资源,但它不会提前执行JavaScript或渲染页面的任何部分。最初,预渲染会消耗大约100MB的内存,当某些组件如媒体被预渲染时,可能会破坏用户界面。 目前使用无状态预取的实现方式消耗的内存要低得多,约为45MB,同时还能减少页面加载时间。预取是由一个带有预渲染资源提示的链接元素触发的。无状态预取是在一个新的专用渲染器中进行的,该渲染器与可见标签隔离,不会破坏用户界面。无状态预取过程缓存了所需的资源,但并不渲染它们。除了更新DNS缓存和cookie存储之外,它也不会修改浏览器的状态。在所有子资源加载完毕后,新的渲染器会被杀死。当用户请求时,会创建一个新的渲染器来渲染页面。 有了一个无状态预取的预渲染实现,即时页面加载的目标仍然无法实现。在探索如何实现即时页面加载之前,让我们看看一些开箱即用的选项,这些选项实现了预取的推测逻辑,也可能与预渲染的实现有关。 **使用第三方库的智能投机** --------------- 开发人员可以洞察人们如何使用他们的网站,并利用这些知识来决定什么应该被预取或预渲染。这些使用趋势往往会随着时间的推移而变化,所以开发者需要根据网站的最新分析数据来更新其资源提示。 还有一些库,如quicklink和guess.js,它们使用启发式方法来确定哪些资源应该在运行时被预取。有了这些库,开发者不需要猜测什么应该被预取。这些库会根据可用的数据作出决定。 **快速链接** -------- Quicklink使用Intersection Observer API来确定哪些链接在视口中,如果用户没有使用慢速连接,则在浏览器空闲时预取这些链接。它使用网络信息API来确定连接的类型以及是否启用了数据保存模式。Quicklink是一个轻量级的库,你可以在多页面应用和单页面应用中使用,以加快导航速度。 **Guess.js** ------------ Guess.js实现了基于Google Analytics或类似分析提供商生成的报告的预测性预取。这些基于分析的预测被用来预取用户可能需要的资源。 现在让我们看看如何在浏览器中建立类似的逻辑,以及需要哪些额外的工具来支持它。 **实施改造后的预渲染解决方案** ----------------- 目前的预渲染实现并没有解决几个限制。以下是我们讨论的一些限制,以及建议的可以改进预渲染的解决方案 - **触发器。**目前是唯一可以在浏览器中启用预渲染的触发器。对于页面上每一个符合预渲染条件的链接,在开发过程中需要在文档中包含一个额外的资源提示。 由于预渲染的要求可能会改变,建议的解决方案应该允许用户为符合某些标准的链接指定一揽子触发器。这已经通过后面详细讨论的推测规则API成为可能。 - **跨源预处理**。当prender的目标链接是在同一个源头上时,不需要很多额外的检查。然而,当它指向一个不同的来源时,可能会有浏览器应该解决的隐私问题。例如,在预渲染一个跨原点的页面时,应该省略用户的证书,因为在实际导航发生之前,响应不应该是个性化的。然而,当用户导航到该页面时,可以提供与用户有关的信息。为了支持这种两阶段的方法,应该有一种方法可以让目标页面选择加入跨源页面的预渲染。 - **预渲染浏览环境。**目前,有不同类型的顶层浏览环境可用。例如,一个窗口中的标签或一个页面上的iframe使用不同的浏览上下文。应该为预渲染的内容创建一个类似的顶层预渲染浏览上下文。 预渲染的浏览上下文应该类似于一个不可见的标签,并且应该施加额外的限制。所有破坏性的API,如播放媒体或可能破坏用户界面的权限提示,应该在这个浏览上下文中被禁用。 预渲染的浏览环境也可以被激活。当用户导航到一个预渲染的页面时,激活应该发生。当激活时,预渲染的页面将切换到一个新的顶层浏览上下文。 - **Portals**Portals是一个新提议的HTML元素,它能够实现页面之间的无缝和即时导航。它将允许你显示预渲染的内容,如下所示。 ``` ``` 这个元素将在预渲染的浏览环境中提供一个预渲染的页面预览。这意味着页面预览将具有限制性的权限。开发者可以通过代码激活该上下文,例如,点击事件,在嵌入窗口中用动画扩展门户的全页面视图。 **预取和预渲染的浏览器内推测规则** ------------------- 上一节中讨论的预渲染最重要的部分之一是通过提议的推测规则API提供的预渲染触发器。开发者可以使用推测规则API,向浏览器表明空白权限,以推测和预取或预渲染符合指定标准的页面。 这些规则帮助浏览器确定网站认为用户会感兴趣的一组初始页面。然后,浏览器可以根据设备或网络特性、页面结构、视口、光标位置、过去在页面上的活动等应用额外的启发式方法,以决定哪些页面需要预制或预取。因此,像QuickLink或Guess.js实现的推测逻辑可以由浏览器本身实现。 推测规则可以被指定为内联脚本标签中的JSON对象或外部资源。例如,用于预处理的推测规则可以定义如下。 ``` ``` 这里,有两种类型的规则被定义为预渲染资源提示。 - 列表规则适用于给定的URL的列表。分数值用来表示用户下一步导航到这些URL之一的可能性有多大。分数值可以在0.0和1.0之间,默认为0.5。 - 文档规则适用于一个文档,意味着一个页面内的所有链接元素都可以被浏览器猜测。链接元素的子集可以通过包括if_href_matches或if_not_href_matches和if_selector_matches或if_not_selector_matches过滤器来选择。 这里href_matches用于匹配链接的URLs,而selector_matches用于匹配CSS选择器。 **同源预渲染的试验** ------------ 涵盖了之前讨论过的一些功能的预渲染的初始实现可以作为Chrome原点的试用版,它将在Chrome 94到98之间运行。以下是该试用版中的主要功能。 - **触发器**推测规则API的某些功能可用于指定触发器,以预呈现同源URL。目前只支持 "列表规则 "格式。另外,对于同一来源的网页,每个页面只允许进行一次预渲染。 ``` ``` **如果指定了多条规则,Chrome浏览器总是根据第一条规则进行预处理。分数属性不被使用。规则可以被添加,但规则集的删除会被忽略。** ------------------------------------------------------------------- - **受限制的API。**可能会破坏用户界面的API,如地理定位、网络串联、通知、网络MIDI和空闲检测,将被推迟到预渲染页面被激活。 - **会话访问。**预置页面在创建时克隆了标签级会话的会话对象。在激活时,它丢弃这个克隆,并再次从标签中获取最新的会话对象。 - **资源。**预置页面可以像普通页面一样加载所有的资源,除了跨源iframe,它只在激活时加载。Cookies和存储API的功能也和普通页面一样。 - **试用用途。**在指定投机规则的页面和作为预渲染目标的页面中,都必须包含原点试用令牌。 **试用的使用** --------- 一旦您开始使用试用版,您就可以通过使用现有的Chrome工具来检查页面是否被预渲染,并研究其性能影响。 该页面是否被预渲染了?# chrome://process-internals页面可以告诉你是否存在一个预渲染的页面。 ![TEh2wBHOaslCV6zbqWHy.png][3] 通过推测规则启动预渲染的页面和预渲染的页面都将在同一个webcontents块下,但可以通过预渲染关键词来区分。 ![9U3igmdttYqWWJ017EIy.png][4] **是否激活了预渲染的页面?** ---------------- 在预渲染后,下一步是激活。为了检查是否确实是预渲染的页面在导航时被激活,而没有发生新的页面加载,你可以在导航发生后打开Dev Tools控制台。执行下面的脚本,检查控制台中activationStart的值。 ``` let activationStart = performance.getEntriesByType('navigation')[0].activationStart; console.log(activationStart); ``` activationStart的非零值将意味着预渲染的页面被激活。 **它是瞬时的吗?** ----------- activationStart的值是一个时间戳,可以与First Paint和First Contentful Paint的值进行比较,以确定预渲染页面以用户为中心的性能指标。 ``` // When the activation navigation started. let activationStart = performance.getEntriesByType('navigation')[0].activationStart; // When First Paint occurred: let firstPaint = performance.getEntriesByName('first-paint')[0].startTime; // When First Contentful Paint occurred: let firstContentfulPaint = performance.getEntriesByName('first-contentful-paint')[0].startTime; console.log('time to first paint: ' + (firstPaint - activationStart)); console.log('time to first-contentful-paint: ' + (firstContentfulPaint - activationStart)); ``` 将firstPaint和firstContentfulPaint的值与使用试用前的值进行比较,可以帮助你衡量性能影响。还建议你使用真实用户监控(RUM)方法来衡量原点试验的性能。 **演示** ------ 要查看预渲染试验的简单演示,请在Chrome中启用enable-prerender2标志。你需要启用该标志才能使演示生效。 ![zPQ21UocTuIb0qpNabiD.png][5] 该演示提供了使用和Speculation Rules API的三种不同页面类型的预渲染选项。你可以点击每个可用的选项来检查是否发生了预渲染。 ![FKQOzMjXpwRZAarD0RET.png][6] 你也可以通过点击页面的链接来比较每个案例的过渡情况。 ![d4aNnm3A4PNN2h9iPrVa.png][7] ![Gjbu7HMTr9bDP9Qa1hDz.png][8] 这个起源试验的目的是提供通过浏览器近乎瞬时地加载页面的能力,而不依赖于任何外部库。同时,它试图不破坏用户体验,为更复杂的预渲染之旅提供一个良好的开端。 [1]: http://guobacai.com/usr/uploads/2021/11/1179752779.jpeg [2]: https://developer.mozilla.org/zh-CN/docs/Web/HTML/Link_types/prefetch#browser_compatibility [3]: http://guobacai.com/usr/uploads/2021/11/3647226543.png [4]: http://guobacai.com/usr/uploads/2021/11/1407214974.png [5]: http://guobacai.com/usr/uploads/2021/11/1321273315.png [6]: http://guobacai.com/usr/uploads/2021/11/1704617603.png [7]: http://guobacai.com/usr/uploads/2021/11/819499337.png [8]: http://guobacai.com/usr/uploads/2021/11/4067038562.png 标签: 浏览器, 性能优化
评论已关闭