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

前端首屏渲染时间的极致优化

时间:2023-03-27 17:38:22 JavaScript

我们知道,用户体验是web产品最重要的部分。尽可能减少首屏加载时间,更流畅地展示用户需要的内容,将是用户是否留存的关键因素。然而,随着现代Web服务为用户提供的交互行为越来越多,前端项目的复杂度越来越高,每个页面的渲染时间势必会越来越长,从而导致用户体验变差。用户的操作变慢了。为此,前端工程师在首屏请求的各个阶段不断研究,不断探索如何将首屏渲染时间降到最低,力求提供更好的产品体验。CSR(ClientSideRender)浏览器渲染是最简单最适合web应用设计思想的。所谓浏览器渲染就是在用户的浏览器中执行应用程序所需的所有页面显示、前端逻辑和界面请求。很好的实现了前后端的解耦,让前端开发更加独立,让后端实现更加简单。同时,为了缓解用户的等待焦虑,我们可以在异步请求界面时,使用loading状态或者骨架屏来进一步提升用户体验。但是随着业务的复杂度增加,浏览器渲染的开销也会增加。我们无法控制用户使用的机器的性能。在很多情况下,用户使用的机器的性能甚至不足以满足应用程序的需求,导致卡顿甚至崩溃,尤其是在移动端。但是由于前端的高动态,浏览器渲染也会带来较差的SEO。SSR(ServerSideRender)服务端渲染的出现其实早于浏览器渲染。在Web应用开发的早期,所有通过ASP、JSP等模板引擎构建的前端页面,实际上都是服务端渲染的结果。这时候服务端渲染无法解耦前后端职责,所以逐渐被浏览器渲染淘汰。但是服务端渲染在处理首屏体验上有着独特的优势。可以提前在服务器中完成页面模板的数据填充,从而一次性返回完整的首屏内容,从而在面对SEO爬取时获取更有效的关键信息。另外,由于能够在首页快速显示真实数据,所以体验往往比加载状态更好,在TTI中的表现更胜一筹。但是,服务器端呈现有其自身的局限性。因为从本质上讲,SSR服务并不能和前端页面完全解耦。因此,目前市面上比较完善的SSR解决方案,只是解决了首屏服务端渲染,采用同构的方式,增加了一层节点中间层,解决了前端和SSR服务更新同步的问题,并与后端Project解耦开发。但这无疑增加了项目的复杂度,而且随着业务的复杂度越来越高,服务端渲染往往需要调用多个接口来请求数据和填充页面,这可能会导致TTFB存在一定的劣势。当然,最重要的是服务端渲染对服务器的负载要求很高。上图是参考字节某项目SSR服务的单机QPS承载性能。我们可以看到,对于一个大流量的web应用,提供一个更复杂的SSR服务的成本是相当高的,而且需要大量的资金去堆机器。因此,我们需要从降本增效的角度来评估SSR带来的ROI是否达到预期。NSR(NativeSideRender)在移动互联网的浪潮下,移动端的功能日新月异。那么,Web应用能否利用Native的性能提升页面渲染性能呢?答案是肯定的,这就需要对NSR进行介绍了。Native渲染的本质还是SSR,只是把提供服务的服务端变成了客户端。由于需要使用客户端功能,这种实现通常应用在手机APP或PWA下。当点击链接时,首先借助浏览器启用一个JS运行时,加载APP中存储的Html模板,发送xhr请求预加载页面数据,然后在客户端本地进行拼接渲染生成Html带有数据的第一个屏幕。形成第一个NSR。同时可以将首屏的Html缓存在客户端,用于下次打开页面时stale-while-revalidate的缓存效果。由于NSR将服务端的渲染工作放在了客户端的各个独立设备上,既实现了页面的预加载,又不会增加服务端的额外压力。达到秒看的效果。这种能力在有客户端或支持PWA的应用中被广泛使用。比如手Q、腾讯文档APP,都具备通过APP内离线包加速首屏渲染的能力。ESR(EdgeSideRender)那么,对于纯Web应用,由于兼容性等原因暂时无法支持PWA页面,是否有合适的首屏渲染加速方案呢?随着云计算和边缘计算的快速发展,前端页面也需要考虑分布式请求处理优化。我们知道CDN节点比真正的服务节点更贴近用户,能够更快的返回内容。所以我们可以在CDN上缓存静态的Html内容模板。收到请求时,首先快速返回静态模板页面给用户,同时向后端发起请求,请求CDN服务器上页面的动态部分,将获取到的动态内容继续返回给用户.其实这里就是利用了HTTP的SSE(ServerSendEvents)协议,通过服务端向客户端发送一个单向的事件流,实现同一个Html文件的分块传输预渲染。最佳实践?这也是我们最近在腾讯文档中探索和实践的。通过服务中间节点的流式传输能力,实现多级首屏渲染加速。对于一个复杂的前端页面,可能需要在首屏加载和计算的资源种类很多,包括需要客户端解析执行的JS动效,需要数据碎片化的展示页面等。服务器直接获取数据。一般来说,客户端只能等待服务端获取到碎片数据并生成SSR渲染的HTML,然后才能开始脚本解析和js资源拉取,最终渲染出完整的页面数据和动效。而且既然他们需要的计算方法不同,为什么不能并行进行呢?在版本发布之前,我们可以解析服务器没有直接发送过来的模板HTML,提取所有需要发起资源请求的外部脚本URL,生成一个HTMLHeader结构,将Header内容伪装成普通的HTMLCached在CDN节点中。结合我们前面介绍的HTTPSSE协议,当用户请求时,我们可以最快的速度将CDN中的HTML头返回给用户,让用户的浏览器提前拉取和解析外链资源。同时CDN节点将用户的请求转发给真实服务器,让服务器获取真实数据返回给客户端。由于客户端已经提前拉取了外链资源,客户端在收到服务端分片的SSR后,可以直接将真实数据渲染到页面,无需等待再次解析外链资源。由于并行关系,这种SSR和NSR的混合方式可以大大减少复杂页面的首屏渲染时间,提升用户体验。以百度首页的请求为例,通过ChormeNetwork提供的瀑布图,我们可以直观的看到一个请求的执行过程。我们可以看到,除了DNS寻址和SSL连接建立是我们无法控制的,大部分的请求时间是在等待服务器响应,请求服务器(CDN)的时间,以及ContentDownload,拉取时间外部链接资源。使用本文的混合方案后,总的请求时间理论上可以降低到Max(A,B)的水平,(A是Waitingforserverresponse,B是ContentDownload)。(当然,在实际运行中,由于CDN节点做的是请求转发,具有SSR能力的页面请求返回时间会更长)。结束语优化前端页面首屏时间是一个永恒的话题。本文介绍了前端行业优化首屏时间的过程,并提供了混合SSR和NSR的新思路,通过并行处理进一步改善耗时任务。首屏加载时间,希望能给大家提供一些参考价值。