返回

触及Webview陷阱,伪元素动画带来的崩溃

前端

发生了一次伪元素动画引起的webview崩溃

引言

这篇文章将分享一个真实的技术案例:在移动端H5项目中,滥用伪元素动画导致了页面崩溃。如果您正在进行移动端开发,那么这篇文章值得一读。在遇到类似问题时,可以通过检查是否有不必要的伪元素动画来排除故障。

背景

前不久做了一个imo年终盛典的h5移动端活动项目,活动主页有三个排行榜页面,以及任选其一随机选取查看更多。

四个页面均有一个通用样式,是一个旋转圆圈进度条,和排行榜信息叠加展示。

问题复现

项目测试的时候都是正常的,但是众所周知,h5项目总是会存在千奇百怪的兼容问题,永远可以找到你想不到的坑。

问题复现时,页面只有旋转圆圈进度条在转动,排行榜信息一直加载不出来。通过远程真机调试查看了下,请求都正常发送了,接口也都返回了正确的数据。那就只能是返回的数据在页面展示时出了问题。

伪元素动画的罪魁祸首

通过逐一排查最终定位到了伪元素动画是罪魁祸首。去掉伪元素动画,排行榜信息就能正常加载并展示。

伪元素动画的样式如下:

.progress-bar .mask {
  animation: progress-bar-mask-rotate 1.2s infinite linear;
  background: rgba(0, 0, 0, 0.5);
  border-radius: 50%;
  height: 124px;
  width: 124px;
}

@keyframes progress-bar-mask-rotate {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

伪元素animation设置了一个旋转动画,这是很常见的动画,在很多场景下都会用到。但是由于历史原因,早期为了更好的兼容性,移动端的很多浏览器都是通过离屏渲染来实现动画的,而离屏渲染的实现本质上就是创建了一个新的图层,层级叠加到页面上。由于webview层级叠加后可能会出现问题,所以现在很多移动端的浏览器(主要是安卓系)都移除了离屏渲染的功能。

但是问题来了,如果开发者在页面上使用了伪元素动画,并且动画的样式是通过transform属性来控制的,那么这些浏览器就会进行层级叠加,也就是创建新的图层。而新的图层会消耗大量的内存,当图层数量过多时,就会导致webview崩溃。

解决方案

在移动端h5开发中,应该避免使用伪元素动画,或者尽量减少伪元素动画的使用。

对于已经使用伪元素动画的页面,可以通过以下方式来解决问题:

  1. 减少伪元素动画的数量。
  2. 使用transform-style: flat来消除层级叠加。
  3. 使用GPU加速来提升动画性能。

总结

伪元素动画是一个非常有用的工具,可以用来创建各种各样的动画效果。但是,在移动端h5开发中,应该谨慎使用伪元素动画,因为滥用伪元素动画可能会导致webview崩溃。

如果您正在进行移动端h5开发,那么希望这篇文章能够帮助您避免出现类似的问题。