当前位置: 首页 > Web前端 > HTML

HTML性能优化-Prerender2.0机制解读

时间:2023-03-28 12:11:37 HTML

1.前言Log是一种按时间顺序进行的Prerender(预渲染),是指用户提前加载网页中的资源,并在此之前进行解析渲染工作打开网页,让网页真正阅读打开时,以最快的速度呈现。理想情况下,打开预渲染页面几乎是瞬间的。Chromium过去一直支持Prerender(Prerender1.0,从2011年到2018年使用)。API的使用方法如下。对单个链接执行预呈现。由于该能力的使用需要较高的设备资源消耗,因此不太实用。大,导致没有被广泛使用,逐渐被废弃。但是,此API随后应用于NoStatePrefetch。NSP机制只预加载目标网页中的关键资源,不进行后续的渲染工作,也不执行JS,即通过减少资源加载时间消耗来提升页面性能,但无法通过预渲染及时展现页面效果。Chromium从M94重新引入了Prerender机制(Prerender2.0)。Prerender2.0是一种新的预渲染技术。该版本着重于提高预渲染页面的准确性和减少执行预渲染所需的设备资源量,缩短页面加载时间,改善用户体验并降低设备功耗。Prerender2.0比Prerender1.0更加灵活、智能和可移植,可以更有效地提升页面加载速度丨1.1多页面架构(MPArch)MPArch(MultiplePageArchitecture)多页面架构,该架构使用单个WebContents模型在一个WebContent中管理多个页面(可见/不可见),WebContents和Page不是一一对应的。单一的WebContents模型非常适合BFCache、Prerender等需要在同一个tab中支持多个页面的功能。Prerender2.0建立在MPArch之上,MPArch使用单一的WebContents多页面模型。但是,Prerender1.0不支持此功能。而是为每个预渲染页面创建一个新的WebContent,每个WebContent只对应一个预渲染页面,即Prerender1.0采用了多WebContents模型。图片来自铬。可以看出,Prerender机制在使用单WebContents模型时相比多WebContents模型在内存占用上有明显的优势。这应该是Prerender2.0比Prerender1.0轻的原因。2.Prerender2.0的使用及效果丨2.1能够使用Prerender2.0机制需要使用新增的SpeculationRulesAPI(https://github.com/WICG/nav-s...),该API可以支持同时触发Prefetch、NSP、Prerender机制。检查您的浏览器是否支持此API。HTMLScriptElement.supports('speculationrules')API使用示例如下:没有在API中使用的原因如下:目前使用的是NoStatePrefetch机制。如果强行改成Prerender机制,将达不到使用过该API的网站的预期(该网站不希望使用该API预渲染URL),资源消耗显着增加,造成网站崩溃的风险风险规则的可塑性差,有些需求不能被这条规则约束。比如SpeculationRulesAPI中require参数的含义很难在这条规则中体现出来,也不可能同时对多个站点进行预处理。由于SpecificationRulesAPI的灵活性,Chromium预计该API将逐渐取代规则,成为开发者使用更多的API。使用上述API在页面发起Prerender后,如何知道用户打开了预渲染页面如下:当activationStart大于0时,表示预渲染页面重用成功。监听“prerenderingchange”事件。//方法1letactivationStart=performance.getEntriesByType('navigation')[0].activationStart;//方法2letwasActivated=false;document.addEventListener('prerenderingchange',(event)=>{wasActivated=true;});丨2.2使用效果使用Chromium提供的视频示例,可以清楚的看到页面在不使用Prerender能力的情况下从0到1显示内容的过程,但是使用Prerender后页面几乎是瞬间显示。效果对比非常明显。3.实现过程(基于M97)丨3.1解析SpeculationRulesAPI解析HTML中的SpeculationRulesAPI后的过程如下:过程如下:将HTML中包含ScriptType的JS内容解析为kSpeculationRules后,开始对原始数据进行JSON解析,匹配有效内容,包括SpeculationAction(kPrefetch,kPrefetchWithSubresources,kPrerender),SpeculationRule(urls,requires\_anonymous\_client\_ip\_when\_cross\_origin);如果SpeculationAction为kPrerender,则开始判断是否满足发起prerender的条件(判断条件如下),如果满足则执行StartPrerendering;发起prerender的页面必须能够看到当前设备平台有足够的内存空间(限制低端机器启用Prerender机制)并且不允许跨域prerender(即prerenderURL必须是与发起prerender的页面相同)Source)(Chromium在M109中表示有望支持跨域prerender)不能在一个页面发起多个prerender。预渲染的FrameTree,而PrerenderHostRegistry管理着所有的PrerenderHosts。可以看出一个WebContents对应多个FrameTree。丨3.2预渲染流程每个预渲染页面都是从PrerenderHost::StartPrerendering()开始,然后执行NavigationRequset中的BeginNavigation方法,后面的逻辑和正常一致页面加载过程。在浏览器线程中判断跳转页面是否需要网络层处理。如果需要网络层处理,则使用网络请求逻辑实现资源请求,返回主文档的首包(也有不需要网络层处理的跳转,比如同Document跳转。)。不管是否遵循网络层逻辑,最终都会走到CommitNavigation这个方法。CommitNavigation是Browser线程向Render线程提交跳转的入口点。CommitNavigation到Render线程后会创建Document、DocumentLoader等对象,DocumentLoader用于处理主文档内容加载完成后的回调通知。接收到主文档数据后,开始解析和渲染过程。预渲染页面会存在于FrameTree结构中,FrameTree由PrerenderHost持有。每个预渲染页面对应一个PrerenderHost对象。所有的PrerenderHosts都保存在以frame\_tree\_node\_id为key的Map中,Map作为成员变量保存在PrerenderHostRegistry中。此时预渲染的Page对用户是不可见的。丨3.3页面加载过程点击链接进入预渲染页面,仍然执行NavigationRequset中的BeginNavigation方法。BeginNavigation方法执行时,会去PrerenderHostRegistry类存储PrerenderHostMap,查找是否有符合要求的PrerenderHost对象。匹配规则是检查当前navigationRequest中的URL是否与PrerenderHost中的URL一致。如果匹配,则匹配成功,返回frame\_tree\_node\_id。找到满足条件的frame\_tree\_node\_id后,开始运行,将prerenderPage的状态切换为active。后续还需要在网络库中请求主文档的首包,检查页面是否可用,并对请求头进行校验,确保可重用的预渲染页面与页面的RequestHeaders和ResponseHeaders一致被加载。以上验证通过后,就可以执行CommitNavigation了。对于BFCache和Prerender页面,先找到stored\_page,将stored\_page的状态切换为active展示给用户。找到满足条件的stored\_page,显示本页,将上一页隐藏存入BFCache。如下所示。4.应用场景由于预渲染页面会消耗大量的设备资源,因此是一种需要谨慎使用的机制能力。如果胡乱使用该能力,不仅不能提升用户的浏览体验,还会耗尽用户宝贵的资源,可能导致卡顿、崩溃等负面影响。Chromium的推荐使用说明Prerender机制只在用户很可能加载某些页面时才推荐使用。这时,Prerender机制带来的正向收益就可以发挥到极致。丨4.1ChromiumChromium将预测技术与Prerender2.0机制相结合,利用预测技术提高预渲染页面的准确率。通过chrome://predictors页面可以看到Chromium对用户行为的预测,如下图所示。绿色表示有足够的??置信度触发预渲染。从上面的例子可以看出,当用户在输入框中输入字符“b”/“ba”/“bai”时,chromium会向“https://www.baidu.com”发起预渲染/"站点,因为经过多次统计后,用户将有足够的把握访问目标站点。Chromium将根据用户输入和选择不断更新预测结果。当置信度>50%(图中黄色)时,Chromium会发起预链接。当置信度>80%时(图中绿色),Chromium会启动预渲染,Chromium会在Sug选项栏中呈现预测结果,协助用户进入目标站点。进入目标站点后,使用“performance.getEntriesByType('navigation')[0].activationStart”检查页面是否通过预渲染渲染。根据activationStart大于0,可以判断页面已经预渲染成功丨4.2对于搜索浏览器,开发者可以参考Chromium的思路,自定义一个合适的预测器,结合Prerender2.0机制使用改善搜索结果页面的屏幕性能,优化用户体验。对于网站开发者来说,可以结合自身的站点情况使用预渲染技术。对于大多数用户将浏览的站点中的某些页面,可以预呈现这些站点。这个场景可以用静态的方式预渲染。以HTML编写的API。也可以针对不同的用户使用不同的策略,根据用户行为,通过JS动态插入需要的预渲染API。衡量网站是否使用了预渲染能力,可以通过添加指标来查看预渲染效果。主要看两个指标,一个是发起的预渲染页数,一个是用户实际加载的预渲染页数(上面说的获取方式)。两个指标的比较可以估计出命中率。网站可以调整其预呈现策略以保持高命中率。五、总结本文主要介绍了Prerender机制的发展历程和现状,介绍了Prerender2.0技术。重点介绍了Prerender2.0技术的使用、实现过程和应用场景。百度APP基于ChromiumM97。这个版本的Prerender2.0机制还处于起步阶段。到目前为止,Chromium仍在改进Prerender2.0技术,因此文档中的内容可能与最新的解决方案略有不同。后期我们将持续关注Prerender2.0技术的发展,探索其在业务中应用的可行性场景,持续优化页面的画面表现,提升用户体验。——END——参考文献:[1]Prerender开发者文档:https://developer.chrome.com/...[2]Prerender官方文档:https://docs.google.com/docum...\_cRAjUeE-bqLL0bslL\_zKqiNeCzNom\_w/edit[3]多页架构文档:https://docs.google.com/docum...推荐阅读:百度工程师谈分布式日志百度工程师带你熟练理解ModuleFederation使用Golang泛型简化代码编写Go语言DDD实践初级文章Diffie-Hellman密钥协议算法研究贴吧低代码高性能规则引擎设计