2021-07-18【性能优化相关】内存泄露导致的浏览器崩溃

最近给客户部署的一个项目,客户反馈说持续运行一段时间后浏览器会崩溃。
收到反馈后,我们使用自己的设备进行测试,持续运行了48小时,页面并没有崩溃。后来找到几台老旧机型来测试,运行几小时后确实出现了崩溃的现象。排查原因应该是代码运行中,在某些低端设备上内存释放不及时,长时间运行后内存积累,导致页面崩溃。

在不能强制客户升级硬件设备的条件下,只能通过优化代码,排查可能存在内存泄漏地方。

1、页面中有很多通过svg和Lottie实现的动画,并通过v-show来控制不同动画的显示和隐藏。通过调试发现,在v-show值为false,即动画display:none的情况下,动画依然在占用内存,所以在优化时将v-show改为了v-if。

2、页面中的动画多处使用了setInterval定时器,通过封装公共方法,使用requestAnimationFrame和setTimeout代替setInterval。

3、对于一些简单功能,如显示当前时间,去掉插件,通过原生js实现。同时对于页面中外部依赖的处理、第三方插件的按需引入。

因为Network面板记录了与服务器交互的具体细节,所以可以通过Network面板来查询当前页面的资源请求。
在这里我们可以看到发起的请求数量,传输体积以及解压缩后的体积,同时还可以知道哪些资源是命中了强缓存,哪些资源命中的协商缓存。

拓展

-关于Lottie动画

Lottie 是 Airbnb 开源的一套跨平台的完整的动画效果解决方案,设计师可以使用 Adobe After Effects 设计出漂亮的动画之后,使用 Lottic 提供的 Bodymovin 插件将设计好的动画导出成 JSON 格式,就可以直接运用在 iOS、Android、Web 和 React Native之上,无需其他额外操作。

关于Lottie动画 https://juejin.cn/post/6844903661760413704

-下面解释一下使用requestAnimationFrame 的原理

  • 何为requestAnimationFrame
    window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。

注意:若你想在浏览器下次重绘之前继续更新下一帧动画,那么回调函数自身必须再次调用window.requestAnimationFrame()。

  • requestAnimationFrame的优势
    requestAnimationFrame 比起 setTimeout、setInterval的优势主要有两点:
    1、requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧。
    2、在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的的cpu,gpu和内存使用量。

  • 关于requestAnimationFrame的使用 - 用js实现一个无限循环的动画。

//大家首先想到的肯定是定时器吧~



    Document
    


效果图.gif

那我们使用requestAnimationFrame函数 试试




    Document
    


随之而来的,有个问题:效果是实现了但是怎么停止requestAnimationFrame函数?是否有类似clearInterval这样的类似方法?
答案是确定的 必须有:cancelAnimationFrame()接收一个参数 requestAnimationFrame默认返回一个id,cancelAnimationFrame只需要传入这个id就可以停止了。




    Document
    


2、如果我想动画频率降低怎么做,默认情况下,requestAnimationFrame执行频率是1000/60,大概是16ms多执一次。
如果我们想每50ms执行一次怎么办呢?




    Document
    


//@我是一个前端

你可能感兴趣的:(2021-07-18【性能优化相关】内存泄露导致的浏览器崩溃)