毕业之后工作经历主要分为两个阶段,一个是面向 to C 业务,干了差不多 9 年,目前在做 to B 业务,干了差不多 3 年。个人感觉 to B 业务比 to C 业务要难干许多。产品的周期,对产品的兼容性要求远比to C
业务高。to b 业务尤其是管理系统相当复杂。经常需要排查内存泄露问题,在 to C 业务场景,很少去关注这个问题,更多的是关注交互效果。
常见的内存泄露问题,当某个模块,或某个视图销毁时,未销毁绑定的事件,导致内存泄露,未清除的定时器,一些 dom 引用未释放 等导致内存泄露。
这种情况很容易排查,在 memory 面板打内存快照,很容易找到泄露点,如果对代码属性,基本上看代码,立马就能够发现问题点。
在上个月,和同事排查一个内存泄露问题,在排查业务方代码以及框架相关代码之后,确认没有任何问题的情况下,通过逐一对比法,编写 demo 确定,该问题是 chrome 浏览器的问题。
复现场景
删除一个正在运行的动画 dom 节点,会留下 detached elements.
<!DOCTYPE html>
<html>
<head>
<title>方块从左到右动画</title>
<style>
.square {
width: 50px;
height: 50px;
background-color: red;
/* 你可以修改颜色 */
position: absolute;
/* 关键:使用 absolute 或 fixed 定位,方便移动 */
top: 50px;
/* 初始垂直位置,可以调整 */
left: 0;
/* 初始水平位置,从左边开始 */
animation: moveRight 2s linear infinite;
/* 应用动画 */
}
@keyframes moveRight {
from {
transform: translateX(0);
/* 动画起始位置:不位移 */
}
to {
transform: translateX(200px);
/* 动画结束位置:向右移动 200px,可以调整 */
}
}
/* 添加暂停动画的类 */
.animation-paused {
animation-play-state: paused;
}
</style>
</head>
<body>
<div id="animatedSquare" class="square"></div>
<button id="removeButton">移除方块</button>
<script>
let square = document.getElementById('animatedSquare');
const removeButton = document.getElementById('removeButton');
// 存储事件监听器引用,以便后续移除
const handleRemove = () => {
if (square) {
// 1. 使用animation-play-state来暂停动画
square.classList.add('animation-paused');
// 2. 给一点时间让浏览器应用暂停状态
requestAnimationFrame(() => {
// 3. 移除元素
square.remove();
// 4. 清除引用
square = undefined;
console.log("方块已移除");
// 5. 移除事件监听器
removeButton.removeEventListener('click', handleRemove);
});
}
};
removeButton.addEventListener('click', handleRemove);
</script>
</body>
</html>
这个问题在 chrome 126 到 chrome 135 之间的版本都存在问题,哪怕是 chrome 136 canary 版本
如下视频所示:
跟 chromium 官方沟通(提 issue)
相关 issue 见:https://issues.chromium.org/u/1/issues/400635410

在即将到来的 136.0.7102.0 版本进行修复
发表评论