如何让你的H5页面首屏秒开?首屏优化方案深度探讨

01

问题背景

随着集团移动化办公需求的陡增,我们输出在集团APP基础上内嵌的H5页面也越来越多。在对接开发过程中,我们发现APP对接一些H5页面首屏打开时间非常慢,甚至达到8s到9s的等待时长。针对该问题,技术团队不断摸索去尝试优化H5页面首屏等待时间,以实现H5页面首屏达到秒开。下面就问题排查、过程分析以及解决方案和大家进行分享。


02

问题排查与分析

在排查之前先了解一下,打开页面都发生了什么?

图片

图1


如上图所示,首先需要通过DNS(域名解析系统)将URL解析为对应的IP地址,然后与对应IP地址确定的服务器建立TCP网络连接,随后向服务端抛出 HTTP请求,服务端处理完请求之后把目标数据放在HTTP响应里返回给客户端,拿到响应数据的浏览器就可以开始走渲染的流程。渲染完毕,页面呈现给用户,并时刻等待响应用户的操作。本文针对HTTP请求、HTTP响应到页面渲染进行分析,针对DNS解析和TCP连接不做分析。


本项目开发是基于APP内嵌的WebView做的H5开发,所以我们先了解一下关于WebView的解析,WebView启动过程大概分为以下几个阶段:

图2(图片来源于https://tech.meituan.com/WebViewPerf.html


观察图2可以发现白屏问题的耗时时间是发生在建立连接到第二次渲染页面之间,也就是在获取静态资源、解析静态资源、页面渲染这个几个步骤中,接下来结合项目看下抓包数据,如图3所示:

图3


由抓包数据结合以上分析可能导致的原因有:

  1. 静态资源CSS、JS等体积过大;

  2. HTTP请求数量过多;

  3. 首页列中图片体积大、没有进行压缩;

  4. 未使用HTTP缓存;

  5. 网络波动造成速度不稳定。


03

解决方案

通过上述的排查与分析,我们针对以上问题逐一进行优化。

1

HTTP请求方向优化

上述分析中的第1项静态资源体积过大会造成每次请求都需要更多的下载时间。第2项,由于浏览器并发数量有限,当请求数量过多时会在请求过程中造成阻塞,针对以上两个方向问题进行如下的优化实践。


HTTP优化有两大方向:

(1)减少请求次数;

(2)减少单次请求所花费的时间。


这两个优化方向在前端开发过程中对应的就是资源的压缩与合并:

(1)我们通过前端开发用构建工具(webpack)对静态资源进行压缩与合并,并进行多次分包与合包的测试验证,最终找到最优方案以减小静态资源体积,并将静态资源进行合包以减少请求次数。

(2)同时静态文件我们也通过Gzip的方式来压缩,将500kb的静态资源压缩到120kb左右,将总包700kb压缩到350kb左右,降低一半以上的体积,如图4所示:

图片

图4


(3)接着观察抓包情况,相对于CSS、JS等静态资源,图片请求的性能提升更是关键的一步,所以我们也要针对图片进行优化。首先在业务方案上进行优化,减少首页列表中要展示的高清图个数。同时在后端开发人员的配合下进行多次尝试,将图片在不降低太多质量的基础上尽量减小体积,并且在不同的场景下使用不同格式的图片(JPEG/JPG、PNG、SVG、Base64、雪碧图等),通过上述方式我们减少了图片数量、图片体积,使页面的性能得到了提升。

(4)上面介绍的都是在请求静态资源的方面,接下来我们就与后端开发人员进行配合使用HTTP缓存功能。静态资源未更新的情况下,不必重复请求服务器资源,使用HTTP协议缓存可以有效减少服务器请求,从而提升页面访问速度。

(5)在项目中使用了CDN,以便静态资源可以通过更近、更快的渠道获取。

2

浏览器渲染层面优化

上面介绍完HTTP方向的优化方案,接下来我们进行浏览器渲染层面优化。首先我们了解浏览器内核可以分成两部分:渲染引擎和JS引擎。其中渲染引擎包括了HTML解释器、CSS解释器、布局、网络、存储、图形、音视频、图片解码器等零部件,我们针对如下述列表中每一个零部件来进行优化,以便让我们的页面在渲染过程中更快。


(1)HTML解释器:将HTML文档经过词法分析输出DOM树;

(2)CSS解释器:解析CSS文档, 生成样式规则;

(3)图层布局计算模块:布局计算每个对象的精确位置和大小;

(4)视图绘制模块:进行具体节点的图像绘制,将像素渲染到屏幕上;

(5)JavaScript引擎:编译执行JavaScript代码。


我们看一下浏览器渲染的整个流程:

图片

图5


基于上面的列表和流程我们来进行渲染层的优化:

(1)在HTML的优化中我们尽量减少DOM结构,减少层级,使HTML结构尽量简化。

(2)在CSS优化中避免使用通配符,只对需要用到的元素进行选择,并通过继承实现的属性,避免重复匹配重复定义,少用标签选择器,多用类选择器替代。

(3)同时优化阻塞资源的加载顺序,将CSS尽早下载到客户端,以缩短首次渲染时间。使用async、defer的方式进行JS文件的加载以防止阻塞。

(4)并且在操作DOM的过程中减少回流与重绘,将需要修改的部分缓存起来,修改完成一次渲染。

(5)使用lazy-load懒加载,初屏时只加载首屏中需要的静态资源和图片,其他资源实现异步加载。

(6)在首页中使用节流防抖,将scroll 事件、键盘事件等通过对事件对应的回调函数进行包裹,以自由变量的形式缓存时间信息。最后用setTimeout来控制事件的触发频率,通过闭包的形式实现节流防抖,以减少请求或者操作DOM。


我们通过上述HTTP请求/响应和浏览器渲染两个层面对项目进行了优化,通过如图6所示的抓包结果来进行优化前后的对比,可以看出优化达到了非常好的效果,优化后的请求体积减小了85%,优化后打开的时间在1.5s左右,相对优化之前速度提升了几倍,证明我们的优化使用户有了更好的体验。

图片

图6


04

总结

在项目开发的初期,我们经历了技术选型,尝试了多种技术栈。为了解决长列表页面中的定位问题,从初始的jQuery换成了可以提供更好用户体验的单页应用技术栈Vue,它的模块化可以让开发人员进行更好的开发与维护。在开发的过程中,通过上述几个方向诸如网络如何请求、页面如何渲染、浏览器的处理方式,我们进行了性能优化并达到了非常好的效果。当然如果想拥有更好的用户体验,还可以通过更多的方式让页面变得更加友好,例如可以通过服务端渲染使我们的首页只需要解析HTML,减少很多其他耗时的步骤,让页面可以有更好的体验。图片还可以使用WebP的格式以减小体积、提高质量。应用PWA可以让我们的页面做到像客户端一样离线访问。当然好的优化针对不同的项目都是需要有相应的取舍,希望大家可以通过上述的内容,结合自己开发的项目做出最适合的优化。


猜你喜欢

转载自blog.51cto.com/15127571/2665856