核心就这一句🏋️
结论:至少Element系及AntD的骨架屏组件动效实现有性能(稳定占用一部分CPU资源)问题,但不影响正常使用。
事情是这样的🎸
某天办公时一时兴起打开了任务管理器,看见Chrome浏览器对应的进程有几个一直在跑,类似下面这样:

由于不清楚每个具体是对应的什么,随即好奇的进行了右键->结束任务操作,有的结束后页面崩溃了,有的结束后开发者工具自动退出了,直到有一个结束后伴随着页面一闪而过......竟然死灰复燃了,而且如此循环,如此往复,给我了一点小小的震撼,我看了看页面,有点懵逼。

良久,打开开发者工具后发现即使在没有对页面做任何操作的情况下,通过 Performance monitor
可以看到也一直有稳定的10%左右的CPU占用,类似下图:

然后在不操作页面的情况下,录制了一段时间内的性能表现情况,从中可以看到一直在循环跑某特定任务:
(防杠备注:截图用的Element官网页面的做示例,后同)
放大来看单个任务里面并没有跑JS相关的任务执行,而是规律的内容绘制:

所以排查方向就是看是否有样式层面的循环变动,一开始埋头在代码里面去把页面涉及到的样式代码看了个遍,但最终一无所获,确实没有写什么动态的样式代码,直到某一刻在观察页面时看见了某个偏于一隅的正在loading的小内容块......我心里还是咯噔了一下(内心OS:不可能,这绝对不可能,这可是用的组件库的骨架屏组件),我终于还是抬起了不太相信的手指做了一系列的操作:鼠标放到骨架屏上 -> 右键 -> 检查 -> 鼠标放到该元素上 -> 右键 -> Delete element
CPU直接躺平了,占用率降为0%,就像这样:

原来是这样的👨🏻⚕️
直到这时我第一反应依旧是当前我用的版本或者用法是不是有问题,又跑到官网去看了骨架屏组件页面验证了下,结果也是一样的情况,然后看了下具体的css写法:

css
.el-skeleton.is-animated .el-skeleton__item {
background: linear-gradient(90deg,#f2f2f2 25%,#e6e6e6 37%,#f2f2f2 63%);
background-size: 400% 100%;
animation: el-skeleton-loading 1.4s ease infinite
}
@keyframes el-skeleton-loading {
0% {
background-position: 100% 50%
}
to {
background-position: 0 50%
}
}
实现逻辑比较简单,在无限循环的动画里面,通过改变 background-position
来实现动效,而它的改变会触发重绘,重绘通常由CPU处理(除非触发GPU加速),频繁的 background-position
动画就导致CPU频繁处理重绘任务使得CPU占用率稳定居高不下。理论上的优化方案就是改用 transform
去实现该动效(至于是否能实现同样的动效还有待研究尝试,但我目前觉得吧这个组件的开发攻城狮们应该是有尝试过,只不过由于某种未知原因所以都采用了现在的实现方案)。
后面又看了下 ElementPlus
的骨架屏也是一样的情况,两者实现代码基本一致,但有个特殊情况是 ElementPlus
骨架屏的CPU占用率稳定在10%左右,而 ElementUI
的却稳定在8%左右,我盯着看了好一会儿,确实是这样,暂未深究,值得玩味。

Ant Design
亦是如此:

至于更多的其它组件库就没一一验证了。
最后我想说🍇
骨架屏的应用场景大家都知道,是为了更好的用户交互体验,一般不会专门拿来用作动画场景(但可能出现类似这样的动效实现写法),在loading结束后就没有了,所以倒也不至于导致页面运行存在稳定的额外性能消耗,但基于此问题可以延伸出性能问题排查、动画性能优化等开发过程中可能出现或遇到的场景。我自己平时没咋写过动画(翻看了下之前唯一一次写过的动画是老老实实的用 transform 做的),虽然相关理论知识知晓,但当真的看到骨架屏这个小小的动画所带来的CPU消耗情况时才能真切感受到相关知识的分量。