目录
一、前言
最近我司的小伙伴在项目上遇到一些问题,是关于性能上的,因此我们探讨了一些关于前端性能优化方法,因此有了本文~
耐心看完,你也许有所收获~
二、内容概述
本文先从页面的生命周期起了解整个链路过程,再针对各个过程简单概述一下可以优化的点,本文没有具体的方法,只是先概述一下,下一篇我们再具体分析各个可实现的方法,本文大致内容概述如下:
三、页面生命周期
什么是生命周期?通俗地说就是一个事物从诞生到消亡的过程,这个过程被称作生命周期,那么套用在页面上,生命周期自然指的就是页面的诞生到页面的创建完毕;
那么,不妨思考一下,页面的诞生是从什么时候开始的,是页面上开始渲染类似于Vue中的mounted吗?其实不是,页面的生命周期起始,其实应该从浏览器中输入了URL开始算,直到页面渲染出来为止;
大致流程如下:
当我们在浏览器输入一个url网址,那么首先浏览器会针对url创建一个 网络请求的线程,创建的过程中会对这个url进行解析,比如解析出host,解析出端口prot等等;
当创建完毕,那么自然要开始 建立http请求 了,这个请求的过程中就会有我们日常说的“3次握手,4次挥手”;
请求建立成功,后端会以数据包的形式将前端包发送到浏览器上,这个前端包就是我们日常前端开发的项目代码,主要就是Html+CSS+Javascript;
浏览器接收到数据包后开始工作,工作存在于在浏览器中的 渲染进程 ,大致这么个流程:
那这个和我们的性能优化有什么关系呢?关系肯定是有的,这个链路中的任何一个环节出现问题,体现到终端用户的感知上就是“网页打不开”,“打开的好慢”,“卡顿严重”等等问题;
因此,只有知道了这个完整的链路,才能对这个链路中的各个环节进行优化,从而达到前端性能优化这个最终目的;
我们日常说的性能优化往往是针对第四个环节的,是代码层面的,但这有时候并不能解决问题,如果真的出现性能问题,那么首先要确认的是这个性能问题是在哪一个环节出现的~
四、性能优化
4.1 建立http环节优化
在这个环节最主要的优化就是 减少http请求的数量,这个是优化的核心目的,最直接的手段就是 合并资源,比如,正常情况下需要发起2个http的请求来获取资源,那么是不是可以通过一些构建上的手段,将两个资源打包合并成1个,那么这样就只需要请求一次即可;
当然,减少http请求也包括使用一些懒加载的技术,比如针对图片的请求要在图片即将显示到可视区域的时候再进行请求;
再来就是http协议,当然现代浏览器这个协议都是已经升级过了,这项优化点正常情况下应该是不需要做什么了,在http1.0的协议中,“3次握手,4次挥手”的过程中需要去不断创建http请求,到了http1.1以上,那么此时的tcp是可以复用协议,但如果你的项目真的是http1.0协议,那么是该升级了...
4.2 资源的传输下载(前后端交互)
在这个环节上我们能做的优化站在前端的角度来说依然不是很多,核心的目的大致有两个:
- 压缩资源,减少响应的数据包体积;
- 使用一些缓存技术避免重复发送请求下载资源;
第一点是压缩资源,数据包减小,那么类似于Vue,React这些单页应用在 首次加载的时候白屏的时间就会短,时间越短用户就越不易感知到卡顿,项目中最常见的就是 webpack 和 rollup 等这类工具,通过这些工具对项目的压缩,在不影响代码逻辑的情况下可以大幅减少代码体积;
此外,在打包过程中这些工具往往会同时兼职合并资源的过程,比如原本我们写了3个js文件,在进行打包后工具会自动帮助我们合并成1个工具,好好利用这些工具是优化的一个重点;
第二点是使用一些缓存技术,这些缓存技术浏览器一般会有一套默认的执行方式,因此单页应用往往只有第一次加载的时候会去请求全部资源,从第二次开始就是利用缓存了,不过这里有一点需要注意,缓存也会造成更新不及时,比如我们更新了内容,但用户在使用的时候依然还是老的资源,因此,缓存是把双刃剑,合理的设置缓存策略也是优化的一个技巧;
4.3 渲染优化
这个环节才是我们前端真正日常需要注意的地方,与上面两个环节不同,上面两个环节其实主要是利用工具,尤其是现在脚手架搭建的项目,只要合理的利用其自带的打包工具都能解决压缩,合并的问题;
但这个环节不同,它需要由我们日常写的代码来提升性能,我个人认为核心是 减少不必要的重绘和回流,合理的代码编写 以及 针对不必要的变量进行手动释放;
在性能吃紧的情况下高性能的操作大概率会造成浏览器的未响应,一旦出现未响应,那基本只有关掉浏览器再开这一条路了;
重绘回流相信大家都理解,这里简单解释一下后两点,合理的代码的意思不要出现一些逻辑上的错误,比如死循环,死循环一旦出现结果不用说....
接着是针对不必要的变量进行手动释放,这个我感觉日常执行基本不会到位,更多的是依赖浏览器的垃圾回收机制,比如这样:
// 通过接口获取到了一大串数据
let result = {//...后台数据}
function handle(){
// 正对数据进行了一大串的操作
}
// 结束以后释放
result=null
当我们对这个数据进行了一大串操作以后不在需要了,那么针对result这个变量是需要手动释放的,只有这样处于缓存中的这块数据才会被清理掉不再继续留存,否则我们只能等,等到浏览器自己去执行垃圾回收机制才会被清理,虽然浏览器自己执行在绝大多数的情况下问题也不大,但....怎么说呢,垃圾回收机制只会去清理不再被使用的变量,有时候变量因为我们的编码问题会被一直被占用着,导致浏览器是不会去清理的,越积越多的内存最终导致的结果就不用多说了...
五、小结
本文主要站在整体的角度上概述了一下在整个链路上有哪些可以优化的点,大致有以下一些优化方法:
- 加载上的优化,目的是通过减少http请求,懒加载技术,来减少首屏的加载时间;
- 构建上的优化,目的是减少资源体积和数量,合理利用主流的构建工具,如webpack等来合并资源,压缩资源;
- 缓存优化,目的是避免重复请求,但对于缓存的策略需要仔细斟酌,毕竟有利有弊;
- 渲染优化,目的是降低高性能的操作,比如减少重绘和回流,合理的代码,以及及时释放资源;