快速确认DOM泄漏最省事的方法是执行$$('*').length并观察数值是否持续上涨,该值反映全部DOM节点数(含Shadow DOM和iframe),节点数线性增长是DOM泄漏最硬信号。

怎么快速确认是不是DOM节点在漏
直接看 $$('*').length 最省事。打开 DevTools Console,执行一次记下数值(比如 4218),然后反复触发游戏场景关键操作——比如进入战斗界面 → 退出 → 再进入。每轮操作后重跑 $$('*').length,如果数字持续上涨(4218 → 4592 → 4931 → 5270),基本就是 DOM 节点没清理干净。
别用 document.querySelectorAll('body *').length 替代,它不包含 Shadow DOM 和 iframe 内节点,而高性能游戏常嵌套 Canvas 或自定义渲染层,$$ 是 DevTools 原生支持的快捷 API,结果更可靠。
注意:这个值本身不等于内存占用大小,但节点数线性增长是 DOM 泄漏最硬的信号——尤其在 WebGL 游戏里,UI 层 DOM 节点本该稳定,涨了就说明有“游离节点”挂着没释放。
Performance 面板里盯哪条曲线最有效
打开 Performance 面板,勾选 Memory 和 Screenshots,录制一段完整游戏循环(如加载关卡 → 战斗 → 暂停 → 返回主菜单)。停止后重点看灰色柱状图里的 Nodes 曲线,不是 JS Heap。
立即学习“前端免费学习笔记(深入)”;
Nodes 曲线反映的是当前存活 DOM 节点总数,比内存 MB 数敏感得多。DOM 节点本身内存开销小,但每个节点背后可能绑定事件、样式、数据引用,一旦泄漏会拖垮整个渲染管线。
关键判断点:
– 每次操作结束后的 Nodes 峰值是否逐轮抬高
– 操作结束后曲线是否回落不到初始基线
– 回落过程是否缓慢、拖尾(暗示 Detached 节点未被 GC)
如果 Nodes 曲线和 JS Heap 同步上涨,大概率是 JS 闭包 hold 住了 DOM;如果 Nodes 涨而 JS Heap 平稳,则可能是纯 DOM 引用残留(比如全局缓存 map 里存了已移除的 div)。
Heap Snapshot 怎么定位 Detached 节点源头
在 Memory 面板拍两张堆快照:
– Snapshot #1:刚进游戏主界面时
– Snapshot #2:反复进出战斗场景 3 次后
切换到 Comparison 视图,在 Constructor 列筛选 HTMLDivElement、HTMLCanvasElement、Text,看 Delta 是否为正且数量异常(比如多出 187 个 HTMLDivElement)。
点击其中一行,右侧 Retaining Path 里如果出现类似这样的链路:Closure → function → element
或window.cacheUI → Map → key → detached div
就锁定了泄漏根因。
常见陷阱:
– 游戏 UI 系统用全局 Map 缓存弹窗实例,但销毁时只删 DOM 没删 Map 键值
– requestAnimationFrame 回调里引用了已卸载面板的 ref.current
– Canvas 上层 DOM 覆盖层(如技能提示气泡)被 position: fixed 脱离文档流,又没手动 remove()
WebGL 场景下 DOM 泄漏的特殊风险点
WebGL 应用里 DOM 泄漏往往和 GPU 资源交织,一个没清理的 HTMLCanvasElement 可能同时锁住三块内存:
– JS 堆:Canvas 元素对象 + 绑定的事件闭包
– Blink 原生堆:渲染树节点 + 样式计算结构
– GPU 显存:如果 Canvas 被 getContext('webgl') 初始化过,底层纹理/缓冲区可能未释放
所以排查时不能只看 JS 堆快照。若发现大量 HTMLCanvasElement 的 Delta 为正,要立刻检查:
– 是否调用了 canvas.getContext('webgl').loseContext()(必要时)
– 是否在组件销毁前执行 canvas.remove() 而非仅 canvas.parentElement.removeChild(canvas)
– 是否用 ObjectURL 创建过临时视频/图片,却没调用 URL.revokeObjectURL()
最隐蔽的是:Canvas 上层 DOM 元素(如血条、技能图标)用 transform: translate3d() 触发 GPU 加速,但元素被移除后,浏览器仍为其保留合成层,直到显式触发垃圾回收——这时 $$('*').length 不涨,Nodes 曲线也不明显,但 GPU 内存持续攀升。这种必须结合 Chrome 的 chrome://gpu 和任务管理器的 GPU 内存监控交叉验证。



















