利用浏览器DevTools中对React项目进行内存泄露排查

利用浏览器DevTools中对React项目进行内存泄露排查

场景:用户在某个页面操作时,在监控平台收集到的数据表现为内存占用有逐步提高的趋势,最先想到的是 DOM 元素卸载后其 JavaScript 对象未能被垃圾回收这类内存泄漏问题。同时,如果在 DOM 元素删除时没有完全清理其对应的 JavaScript 引用,那么内存占用就会只增不减,最终影响用户体验。

步骤一:Performance Monitor定性

Performance Monitor 能够在较小的性能代价下展示出网站应用的若干个影响性能和体验的关键参数随着时间变化(用户操作)的趋势,其关键指标如下所示。

CPU usage 网页使用的CPU百分比。默认显示。
JS heap size JavaScript程序在页面上使用的内存量。默认显示。
DOM Nodes 浏览器中DOM节点的数量(跨选项卡)。默认显示。
JS event listeners 浏览器中JavaScript事件监听器的数量(跨选项卡)。
Documents 浏览器中文档对象的数量(跨选项卡)。
Document Frames 浏览器中文档框架的数量(跨选项卡)。
Layouts / sec 浏览器引擎每秒构建页面布局的次数。
Style recalcs / sec 浏览器引擎每秒计算页面CSS样式的次数。

针对内存泄漏问题,可以重点关注 JavaScript 堆大小和 DOM 节点数的变化趋势,并根据以下原则对内存泄漏进行初步的定性判断

  • 其中任何一个出现只增不减的趋势,则可以定性判断存在内存泄漏问题
  • 如果 JavaScript 堆大小只增不减,而 DOM 节点数趋势平稳,则可以定性只在 JavaScript 上下文中出现了内存泄漏
  • DOM 节点数只增不减往往会伴随着 JavaScript 堆大小的只增不减。此时需要关注二者增加的趋势是否同比(增长速度一致)同频(增长时机一致)
    • 如果同比同频,可以定性只有 DOM 元素卸载未清理引用引发的内存泄漏,JavaScript 堆大小的变化只是伴生现象
    • JavaScript 堆大小增长趋势更加陡峭,可以定性同时存在两个内存泄漏源头

当二者的变化趋势满足同比同频,基本可以确定是对 DOM 元素的引用没有清理导致的内存泄露问题。

步骤二:Detached Elements定位

官方文档:https://learn.microsoft.com/en-us/microsoft-edge/devtools-guide-chromium/memory-problems/dom-leaks

Detached Elements 的功能非常明确,即找到所有没有挂载在 DOM 树上,同时还没有被浏览器引擎垃圾回收的 DOM 元素。因为浏览器的垃圾回收本身就是周期性的行为,所以在进行问题排查前,必须手动触发一次垃圾回收行为,保证剩下的就是要排查分析的目标元素。(记住一个要点:每次录制前需要手动回收,以保证数据准确)

DOM对象是占用内存最高的一类对象之一,因此如果在应用程序中频繁地创建和销毁DOM对象,就容易导致内存泄漏。游离的DOM引用指的是已经不在文档中的DOM节点的引用,但是这些引用仍然被保存在JavaScript的变量、数组和对象中,因此这些DOM节点无法被垃圾回收器回收,从而导致内存泄漏。

步骤三:Memory分析

官方文档:https://learn.microsoft.com/en-us/microsoft-edge/devtools-guide-chromium/memory-problems/

Memory 能够建立当前应用的 JavaScript 堆快照,用于进一步分析页面的 JavaScript 对象以及相互之间的引用关系。在已经定位了泄漏源的基础上,可以借助该工具查明目标 DOM 被什么 JavaScript 对象持有了引用导致无法被垃圾回收。

基于这里的快照,我们可以发现发生泄漏的 DOM 元素的 distance属性 是 7,点击之后可以反向追溯其到 Root(浏览器环境下为 window 对象)的完整路径。当然,持有该 DOM 元素的路径通常不止一条,我们只需要关注最短的那条即可。基于此,我们可以构建出其对象持有路径…

[外链图片转存中…(img-Xi1zHZIP-1719410253318)]

在分析了多个发生泄漏的 DOM 元素之后,我们最终定位到XXXX属性持有了已经被卸载的 DOM 的引用,导致用户只要停留在页面,DOM增删情况越多越多内存泄漏得越多。对相关代码进行处理,及时删除引用即可。

小结

在 React 框架中,为了能够方便地建立 DOM 元素与 FiberNode 之间的关联,由框架生成的 DOM 元素会持有其 FiberNode 对象的引用,FiberNode 中同样持有了相关 DOM 元素的引用。因此,无论是浏览器的 DOM 树还是 React 的 Fiber 树,只要有任意一个节点没有被正确释放引用,其自身以及所有子孙元素在两棵树上的对象都无法被垃圾回收。

因此在React项目中,不仅要关心真实Dom的引用,也要关心虚拟Dom及其Fiber节点的引用情况…

  • 18
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue Devtools 是 Vue.js 官方提供的一个调试工具,用于在开发过程对 Vue.js 应用进行调试和监测。当遇到内存泄露问题时,可以通过以下步骤使用 Vue Devtools 进行排查: 1. 确保 Vue Devtools 安装和启动:在浏览器安装 Vue Devtools 插件,然后在项目确保已正确引入 Vue Devtools 的开发版。 2. 打开 Vue Devtools:在浏览器开发者工具,切换到 Vue 选项卡,确保 Vue Devtools 已打开。 3. 观察组件状态和生命周期:在 Vue Devtools ,可以查看当前所有渲染的组件实例。观察组件的状态和生命周期,查看是否存在异常。 4. 检查内存占用情况:在 Vue Devtools 的性能面板,可以查看当前应用的内存占用。如果内存占用不断增长,可能存在内存泄露问题。 5. 分析垃圾回收:在 Vue Devtools 的性能面板,可以查看垃圾回收的情况。如果发现垃圾回收频率较低,可能意味着存在内存泄露。 6. 使用快照:在 Vue Devtools 的快照面板,可以记录当前应用的状态,并随时保存和比对快照。通过比对快照,可以找出内存泄露的具体变化。 7. 分析组件树:在 Vue Devtools 的组件树面板,可以查看整个组件树的结构。通过观察组件树的变化,找出可能导致内存泄露的组件。 8. 排查事件监听:使用 Vue Devtools 的事件监听面板,检查是否存在未正确注销的事件监听器。未移除的事件监听器可能导致组件无法被销毁,从而引发内存泄露。 9. 使用 Heap Snapshot:如果通过以上方法仍无法确定内存泄露的原因,可以使用 Heap Snapshot 功能。Heap Snapshot 可以在内存占用高峰时,记录当前内存的对象实例,从而帮助进一步分析内存泄露的源头。 通过以上步骤,可以使用 Vue Devtools 进行内存泄露问题的排查和分析,找到导致内存泄露的原因,并进行相应的优化处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值