当我们怀疑页面发生了内存泄漏的时候,可以先用Performance录制一段时间内页面的性能变化。你只需要切换到Performance面板,点击Record,然后在页面上正常操作一段时间,最后停止录制即可。
如果录制结束后,看到内存的下限在不断升高的话,你就要注意了 —— 这里有可能发生了内存泄漏。
除了内存增长曲线,Nodes(Dom节点数曲线)、Document曲线以及Listener曲线也同样值得关注,有时候它们对内存问题的定位也很有帮助。
通过Memory面板定位内存泄漏的流程
Gmail团队也在用的 “three snapshot”技巧:
- 打开DevTools, 切换至Memory面板
- 先记录一个堆内存快照
- 在你的页面上执行可能发生泄漏的操作
- 再记录一个堆内存快照
- 重复执行多几遍步骤3
- 最后记录一个堆内存快照
- 选择最后一个堆内存快照,找到顶栏的“All objects”, 切换至”Objects allocated between snapshots 1 and 2”(也可以对2,3执行同样的操作)
常见的内存泄漏场景有哪些?
- console导致的内存泄漏 因为打印后的对象需要支持在控制台上查看,所以传递给console.log方法的对象是不能被垃圾回收的。我们需要避免在生产环境用console打印对象。
- 框架配合第三方库使用时,没有及时执行销毁
- 被遗忘的定时器 例如在组件初始化的时候设置了
setInterval
,那么在组件销毁之前记得调用clearInterval
方法取消定时器。 - 没有正确移除事件监听器(各种EventBus, dom事件监听等) 这应该是最容易犯的一个错误,无论新手老手都有可能栽在这里。
特征:performance里,监听器数量会持续上升
// 版本三 data() { return { debounceWidthChange: null } }, mounted() { this.debounceWidthChange = debounce(this.handleWidthChange, 100) window.addEventListener('resize', this.debounceWidthChange) }, beforeDestroy() { window.removeEventListener('resize', this.debounceWidthChange) }