Ionic 5/JS图片引发内存泄漏导致WKWebView强制白屏刷新问题求助
我们在Ionic框架开发中遇到疑似图片引发的内存泄漏问题:应用长期运行后内存占用过高,稳定性下降,最终会触发WKWebView强制刷新(出现白闪现象)导致应用重置。
该问题会严重影响生产环境可用性,应用长时间运行后切到后台,再次切回前台时也会触发WKWebView强制刷新。
Bug复现仓库地址:https://github.com/4bsolut/cards
复现操作动图地址:https://github.com/4bsolut/cards/raw/main/GIF-2021-10-20-14-07-27.gif?raw=true,该动图为操作「接受/拒绝多张图片卡片」时的录制内容。
内存变化图表动图地址:https://user-images.githubusercontent.com/2399351/138188417-c82eaf86-8a42-483a-b4dd-e973804d3309.gif,可看到应用崩溃、强制刷新重置前内存出现大幅飙升。
复现步骤
- 在Ionic页面中加载内容,比如参考复现代码仓库的实现,加载含图片的卡片
- 按需隐藏或移除已加载的图片
- 不跳转离开当前页面的前提下,继续加载更多图片
- 由于图片对应的垃圾回收/内存清理未正常执行,最终WKWebView内存耗尽
- 应用出现用户输入无响应异常,或直接触发WKWebView刷新
补充信息
该问题在iPhone模拟器中运行正常,但在真机上会出现白闪刷新/崩溃。
测试覆盖真机:iPhone 12 Pro(iOS 15.0.2)、iPhone XR(iOS 13.4.1)
问题排查更新
内存占用过高是由图层问题导致,Ionic官方已提供完整的调试支持,排查结果如下:
该问题包含两个诱因:
向DOM中新增卡片时,WebKit会生成大量图层,导致内存从约30MB飙升到约300MB,卡片移除后图层未被清理,内存占用始终维持在300MB左右。
问题1由cards.component.scss第44行的transition: all 0.3s ease-in-out,和同文件第74行的transition: opacity 0.3s ease-in-out共同引发:all关键字会让浏览器同时过渡cards.component.html第22行卡片元素行内设置的z-index,强制WebKit在动画过程中创建独立图层,大幅提升内存占用。实际仅需要过渡transform属性,建议将all替换为transform;针对图片的opacity过渡规则,建议直接移除,opacity过渡会强制图片合成,同时会导致重叠元素也被合成,进一步抬升内存。
问题2由cards.component.scss第43行的will-change: transform引发:will-change会让浏览器提前对元素做优化,但该属性仅应作为最终优化手段使用,不应用作前置预优化方案,大量元素应用该属性会导致资源占用过高且无法正常释放,建议移除该规则。
总结优化方案:
- 将
.project--card选择器下的transition: all 0.3s ease-in-out修改为transition: transform 0.3s ease-in-out- 移除
.project--card img选择器下的transition: opacity 0.3s ease-in-out规则- 移除
.project--card选择器下的will-change: transform规则
经排查未在Ionic框架代码中发现引发该问题的相关逻辑,可尝试以上三处修改验证是否能解决问题。
内容的提问来源于stack exchange,提问作者Nick Hatter

