前端中的性能优化你知道多少??

162 阅读7分钟

小编昨天的面试中被问到,前端的优化方案你知道多少? 当时就把项目中常见的优化方案说了一些,但是还是觉得自己答得比较少,所以就赶紧整理了一些。

前端中性能优化汇总:

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:减少页面中的冗余代码,提高代码的重复使用率「低耦合高内聚」 :函数的封装->函数式编程和命令式编程

  1. 对不经常更新的数据做缓存,减少非必要的请求「LocalStorage, sessionStorage, vuex/redux,」

  2. 函数的防抖和节流

  3. 避免使用iframe实现页面嵌套,基于vue-router或者react-router-dom实现前端路由

  4. 尽可能是用flex布局,减少float的使用

  5. 对于数据的实时通信,避免基于定时器的ajax轮询,采用更好的scoket. io通信机制

  6. 合理使用闭包,对于不用的堆内存及时释放 以此优化内存空间

  7. 少使用cookie,因为每次向服务器发送请求,浏览器都会把本地cookie传递给服务器(哪怕这个事情是没用的)

  8. 避免死递归和死循环,因为他们都会阻碍JS线程的渲染

  9. 避免内存泄漏

  10. 用字体图标(或者矢量图)代替位图

  11. vue中为了减少DOM-DIFFit算,需要对超长列表进行优化

  12. 音视频数据一定要延迟加载,否则会让页面首次渲染变慢

  13. 不要使用CSS表达式

  14. JS中减少对eval的使用,对于with坚决不用

28,. JS循环的性能: for/while-> Array. prototype. forEach-> for of-> for in(性能最差)

  1. 减少使用table布局

  2. 图片使用BASE64

  3. 对不经常更新的数据做缓存,减少非必要的请求「LocalStorage, sessionStorage, vuex/redux,」

  4. 函数的防抖和节流

  5. 避免使用iframe实现页面嵌套,基于vue-router或者react-router-dom实现前端路由

  6. 尽可能是用flex布局,减少float的使用

  7. 对于数据的实时通信,避免基于定时器的ajax轮询,采用更好的scoket. io通信机制

  8. 合理使用闭包,对于不用的堆内存及时释放 以此优化内存空间

  9. 少使用cookie,因为每次向服务器发送请求,浏览器都会把本地cookie传递给服务器(哪怕这个事情是没用的)

  10. 避免死递归和死循环,因为他们都会阻碍JS线程的渲染

  11. 避免内存泄漏

  12. 用字体图标(或者矢量图)代替位图

  13. vue中为了减少DOM-DIFFit算,需要对超长列表进行优化

  14. 音视频数据一定要延迟加载,否则会让页面首次渲染变慢

  15. 不要使用CSS表达式

  16. JS中减少对eval的使用,对于with坚决不用

28,. JS循环的性能: for/while-> Array.原型。 forEach-> for of-> for in(性能最差)

  1. 减少使用table布局

  2. 图片使用BASE64

正常图片渲染步骤获取图片资源-->编码-->渲染

如果使用BASE64:渲染

虽然让图片渲染更快,但是导致页面代码“超恶”,不方便维护,所以合理利用BASE64。

  +后期在webpack中,我们直接会把小图都BASE64了

  +对于一些不能延迟加载的大图(图片中的信息很重要),我们可以基于BASE64来处理

终极方案:  公司有钱,以上优化都可以不做,直接把资源部署到CDN上