本文正在参加「金石计划」
问题出现背景
公司在做大屏可视化项目时 ,有多个子页面,每个页面都有 3D 场景 , 我负责的是 threejs 模块 , 在项目起步时 , 还没有意识到问题的严重性 , 项目没有出现过崩溃的迹象 , 但是在项目的模块逐渐增加 , 项目体量逐渐庞大之后 , 项目开始在频繁的切屏之后崩溃 。F12 打开控制台 , 发现浏览器报错 : 内存溢出
在 threejs 项目中 , 加载模型之后 , 模型的材质 , 几何体 , 贴图等等都会增加浏览器的内存 , F12 选择memory(内存) 可以查看到
针对这个问题 , 项目创建之初我们做了一些基础的操作 , 例如在每个页面销毁的时候 , 使用常规的清理方法 clear(),尝试清除 threejs 场景中加载模型带来的内存,但是这并没有实现一个好的效果
因为项目中的每一个子页面 , 都需要展示特定的对应的模型 , 所以在重复的切屏之后, 每一次路由切换都会因为需要重新加载场景,并且之前的场景的内存在浏览器中无法清除,内存逐渐增多 , 直到崩溃
探索解决方案
经过一个上午的思考 , 选定的解决方案有 2 个 , 这里主要讲 方案一 , 方案二粗略带过一下
- 对 threejs 创建出来的场景进行统一管理 , 对每一块内存进行追踪,在页面销毁时统一处理
- 利用 iframe 标签,将 3D场景 的渲染统一交给 iframe ,利用 MessageChannel 进行交互
方案一
首先 ,装一个类 MemoryManager 对内存进行统一管理
然后,封装一个类SceneManager对场景进行统一管理 , 以下是简化后的核心代码, 在该类中,对 Scene.add() 方法进行了封装,在往场景添加对象时会同时进行内存的收集。
方案二
来自于官网的方法,利用 iframe 创建新的 window窗口渲染 3D场景,在路由切换时,也不会造成额外的内存,具体原理暂时还不清楚 。 需要解决的问题就是与主窗口的通信问题,这里我使用的是 MessageChannel
原文链接:https://juejin.cn/post/7214546515611992123 作者:你也向往长安城吗