Electron鸿蒙桌面应用内存泄漏?我花了两天才找到元凶
上周在鸿蒙PC上给客户演示Electron项目,刚跑起来还挺流畅,结果不到两小时,风扇就开始狂转,内存从启动时的200M直接飙到2G,页面卡得像PPT。客户在旁边盯着,我脸上挂不住,赶紧找问题——这一找就是两天。
以为是JS内存泄漏?结果方向错了
一开始我理所当然认为是渲染进程的JS内存没释放,按照以往经验用Chrome DevTools抓堆快照,对比多次快照后发现,内存增长主要不在JS堆,而在Electron的Webview部分。
我这个项目需要在页面里动态加载外部网页,所以用了不少webview标签。一开始以为和iframe一样,移除DOM就能自动销毁,结果鸿蒙上的Electron Webview完全不是这回事——它需要显式调用destroy()方法,而且还要手动移除所有事件监听器,不然垃圾回收根本收不回来。
说白了,就是没管好Webview的生命周期。
第一个坑:Webview销毁逻辑缺失
先看我一开始的错误写法:
<!-- 错误示例:没有销毁逻辑 --><divid="webview-container"></div><script>function loadExternalPage(url) { const container = document.getElementById('webview-container'); container.innerHTML = `<webview src="{(mem.rss / 1024 / 1024).toFixed(2)}MB`, heapUsed: `{(mem.heapTotal / 1024 / 1024).toFixed(2)}MB`, external: `${(mem.external / 1024 / 1024).toFixed(2)}MB` }; // 发送到渲染进程显示 if (this.mainWindow && !this.mainWindow.isDestroyed()) { this.mainWindow.webContents.send('memory-update', log); } // 写入日志文件 fs.appendFileSync( path.join(app.getPath('logs'), 'memory.log'), JSON.stringify(log) + '\n' ); }, this.interval); } stop() { if (this.timer) { clearInterval(this.timer); this.timer = null; } }}
优化后的效果
改完这三个坑,应用重新跑起来测试:
个人建议
说白了,Electron在鸿蒙上跑,内存管理比在Windows上要严格得多。我个人建议:
- 鸿蒙上
Webview销毁要加延迟,给系统足够时间释放进程
别等项目上线了被客户投诉才想起优化,那时候改起来就麻烦了。
本文代码遵循MIT协议,转载请注明出处。