小编昨天的面试中被问到,前端的优化方案你知道多少? 当时就把项目中常见的优化方案说了一些,但是还是觉得自己答得比较少,所以就赶紧整理了一些。
前端中性能优化汇总:
1、对于静态资源文件采用“强缓存"和"协商缓存", 目的:让页面第二次及以后加载更快
扩展:描述强缓存的协商缓存(请求头和响应头字段) juejin.cn/post/703990…
如何保证服务器资源更新后,客户端可以抛开本地缓存,从服务器获取最新的信息;
2、在直接操作DOM的时候,要减少DOM的重排(或回流)
-
尽可能使用vue/react等框架,避免直接操作DOM
-
读写分离【扩展:浏览器的渲染队列机制】
-
样式集中修改
-
批量新增元素,基于文档碎片或者字符串拼接等方法,统一插入到页面中
-
尽量可能使用transform修改样式【开启了硬件加速,不会引发回流】
-
要操作的元素尽可能处于单独的文档流(平面)中
3、减少HTTP请求的次数和大小,目的:加快页面的第一次渲染的速度,减少页面白屏的等待时间
原因:同源下允许并发的HTTP数量有限制(大概是5-7个)如果HTTP请求次数过多,剩下的需要排队等待加载,而且因为请求数量过多,也可能会导致网络通道堵塞!!
-
css/js资源进行合并压缩
-
css sprite 雪碧图
-
图片懒加载
-
数据的懒加载(异步加载)开始只发送首屏的数据请求,当页面渲染完,再去发送其他的数据请求 分页或者下拉加载的等操作
-
服务器端开启 GZIP 压缩,可以使传输的内容压缩40%~60%左右
4·骨架屏技术方案,目的:加快页面第一次渲染的速度
「服务器骨架屏」
首屏信息基于服务器渲染(服务器返回结构/样式/数据,前提是服务器抗压能力和处理速度强),其余屏幕信息还是交给客户端渲染! !
「客户端骨架屏」
最开始加载页面的时候,只是用一些框框占位而已(变相的loading效果)
5·基于事件委托来优化事件绑定
原因:减少了堆栈内存的开辟,性能比一个个的做事件绑定提高40%以上;可以给动态绑定的元素做事件绑定
6.DNS 优化 :目的 :加快页面的第一次渲染速度
原则上我们应该减少DNS解析次数[具体做法:所有资源放在同一个域名下(相同的服务器上),第一次解析会有缓存,后续再去获取其他的资源,直接从本地缓存记录中获取DNS 解析信息即可]
但是在实际开发中,我们会根据资源类型的不同,把他们放在不同的服务器上(不同域名下),但是这样就增加了DNS 解析的次数。。。。
在增加解析次数的基础上,我们基于DNS Prefetch(DNS 预解析:就是利用link标签的异步性。在DNS解析的同时,GUI还可以继续渲染。。。)来进行优化:怎么进行优化
7.关于页面中 动画处理原则:
能用CSS搞定的不用JS,即使使用JS 动画,能用requestAnimationFrame实现的也不用定时器(定时器异步的,到时间不一定执行;刷新频率不一样);如果js都搞不定的动画,直接让产品换需求......
8.关于css选择器的优化
+减少嵌套的“前缀”
+减少复杂性
+语义化
9.导入JS资源的优化:目的:加快页面第一次渲染
+放入页面的最底部【避免阻碍GUI的渲染】
+或者设置async或者 defer
10.导入css资源的优化 目的:加快页面第一次渲染
+优先使用内嵌式【可以减少HTTP请求】
+代码过多的情况下,使用外链式
+坚决不用导入式,因为他会阻碍GUI的渲染
11.使用HTTP2.0
HTTP2.0相对于HTTP1.1的优势
-
传输的内容是基于二进制来构建的,这样更加健壮
-
请求头/响应头信息的压缩{客户端和服务器端对头的信息各自缓存一份,每次发送请求,没必要再传递那么多头信息,减少HTTP传输内容大小}
-
服务端主动推送「发送一次请求,服务器端不仅把这次请求的内容返回,而且还可以把与其相关的内容都返回」
-
多路复用「HTTP1.1中,基于TCP三次握手开辟的网络通道,每一次只允许一个请求通过(其余请求排队等待,而且容易导致“线头阻寒"), 而HTTP2.0中一个通道可以允许多个请求同时进行..」
12:减少HTML的层级嵌套,而且使用语义化标签,以此来加快DOM TREE的生成
13:减少页面中的冗余代码,提高代码的重复使用率「低耦合高内聚」 :函数的封装->函数式编程和命令式编程
-
对不经常更新的数据做缓存,减少非必要的请求「LocalStorage, sessionStorage, vuex/redux,」
-
函数的防抖和节流
-
避免使用iframe实现页面嵌套,基于vue-router或者react-router-dom实现前端路由
-
尽可能是用flex布局,减少float的使用
-
对于数据的实时通信,避免基于定时器的ajax轮询,采用更好的scoket. io通信机制
-
合理使用闭包,对于不用的堆内存及时释放 以此优化内存空间
-
少使用cookie,因为每次向服务器发送请求,浏览器都会把本地cookie传递给服务器(哪怕这个事情是没用的)
-
避免死递归和死循环,因为他们都会阻碍JS线程的渲染
-
避免内存泄漏
-
用字体图标(或者矢量图)代替位图
-
vue中为了减少DOM-DIFFit算,需要对超长列表进行优化
-
音视频数据一定要延迟加载,否则会让页面首次渲染变慢
-
不要使用CSS表达式
-
JS中减少对eval的使用,对于with坚决不用
28,. JS循环的性能: for/while-> Array. prototype. forEach-> for of-> for in(性能最差)
-
减少使用table布局
-
图片使用BASE64
-
对不经常更新的数据做缓存,减少非必要的请求「LocalStorage, sessionStorage, vuex/redux,」
-
函数的防抖和节流
-
避免使用iframe实现页面嵌套,基于vue-router或者react-router-dom实现前端路由
-
尽可能是用flex布局,减少float的使用
-
对于数据的实时通信,避免基于定时器的ajax轮询,采用更好的scoket. io通信机制
-
合理使用闭包,对于不用的堆内存及时释放 以此优化内存空间
-
少使用cookie,因为每次向服务器发送请求,浏览器都会把本地cookie传递给服务器(哪怕这个事情是没用的)
-
避免死递归和死循环,因为他们都会阻碍JS线程的渲染
-
避免内存泄漏
-
用字体图标(或者矢量图)代替位图
-
vue中为了减少DOM-DIFFit算,需要对超长列表进行优化
-
音视频数据一定要延迟加载,否则会让页面首次渲染变慢
-
不要使用CSS表达式
-
JS中减少对eval的使用,对于with坚决不用
28,. JS循环的性能: for/while-> Array.原型。 forEach-> for of-> for in(性能最差)
-
减少使用table布局
-
图片使用BASE64
正常图片渲染步骤获取图片资源-->编码-->渲染
如果使用BASE64:渲染
虽然让图片渲染更快,但是导致页面代码“超恶”,不方便维护,所以合理利用BASE64。
+后期在webpack中,我们直接会把小图都BASE64了
+对于一些不能延迟加载的大图(图片中的信息很重要),我们可以基于BASE64来处理
终极方案: 公司有钱,以上优化都可以不做,直接把资源部署到CDN上