当你需要对首屏进行性能提升的时候,很重要的一点就是了解页面加载的整个过程。通过整个过程,我们就可以找到其中影响性能的关键点,瓶颈点,才能有效的提升性能。
当输入url按下回车键的时候,浏览器为了解析ip地址,会首先访问本地是否相应的ip。如果没有则会向DNS服务器发起查询,获取ip地址。然后浏览器通过ip地址找到目标服务器,两者进行TCP三次握手四次回收和TLS协商,建立TCP链接。
链接建立后,浏览器发送http请求,服务端接收之后对请求进行相应。浏览器通过http返回的结果中拿到数据。进行解析和渲染页面。
上面的流程大致就分为下列三个阶段:
客户端请求阶段瓶颈点
这个过程中,本地缓存,DNS查询,http请求就是影响前端性能的瓶颈点。
1.本地缓存
本地缓存可以让静态资源加载更快,当客户端发送一个请求的时候,静态资源可以直接从客户端获取,不用再向服务器请求。
例如一个卡券列表,客户端请求阶段,DNS查询大概是385ms,TCP三次握手协商时间大概是436ms,数据返回412ms。在强网下总共一个请求所需要的时间就大约是1233ms,如果是在弱网3G,2G的情况下就可能需要2s。
就我现在所了解的有几种本地缓存方法:
1.前端自己做缓存:
例如不同tab栏切换列表的时候,可以把数据存在页面上。当用户切换到之前的tab的时候先显示缓存中的数据,再上拉加载的数据的时候再进行数据请求。(vue中这个可以用for循环渲染多个tab,每个tab对应自己的list。这样切换的时候不用自己做缓存数据,页面自己缓存了的。)
2.后端做缓存:需要在服务器上进行配置,一般包括强缓存和协商保存两种形式。
强缓存:指浏览器在加载资源时,根据请求头的expires和cache-control判断是否命中客户端缓存。如果命中,直接从缓存中方读取资源,不会发请求到服务器,反之走完成的资源请求流程。
协商缓存:浏览器会先发送一个请求到服务器,通过last-modified和etag验证资源是否命中客户端缓存。如果命中,服务器将这个请求返回,但是不返回这个资源的数据,还是从缓存中读取数据。如果没命中,不论是资源过期还是无相关资源,都需要向服务器发起请求,等待服务器返回这个资源。
2.DNS查询
DNS每进行一次查询,都要经历从手机到移动信号塔,再到认证DNS服务器的过程。这中间需要很长的时间,但是用户并不想等待这么长的时间。
想节省时间,一个办法是让DNS查询也走缓存。浏览器提供了DNS预获取的接口,我们在打开浏览器或者webview的同时进行配置。
3.HTTP请求
在http请求阶段,最大的瓶颈点就是亲故阻塞。请求阻塞:浏览器为了保证访问速度,默认对同一域下的资源保持一定的连接数,请求过多的时候就会进行阻塞。
浏览器同域名的连接数一般是6个。如果当请求数多于6个时候只能6个并发,其余的得等先返回的请求后,才能做下一次请求。
所以在项目之初,做一些域名规划很重要。可以先看看当前页面需要用到的域名,最关键的首屏中需要用到哪些域名,规划好这些域名发送的顺序。
除域名规划之外,还要解决同域名下的阻塞问题,做域名散列,通过不同域名,增加请求并行连接数。常见做法:将静态服务器地址pic.google.com,做成支持pic0-5的6个域名,每次请求时随机选一个域名地址进行请求。因为6个域名同时可用,最多可以并行36个连接。不过域名个数对越多,越分散,又会涉及到多域名之间无法缓存的问题。