本篇文章是最后一篇,主要讲一下在浏览器端的一些实现。和浏览器热更新的细节。
浏览器端依赖
socket.io
——浏览器端仅仅依赖socket这个去和服务端通信
通信逻辑
1 | // 建立连接 |
对css/less更新的处理
这个原理比较简单,页面监听到样式的修改,重新加载一次样式即可,简单的覆盖。
但是存在一个潜在问题,因为样式是简单的覆盖,所以,如果修改是删除了样式,是无法生效的。
举例:
修改前:
1 | display: none; |
修改后:
1 | display: none; |
删除的border
和margin-top
其实是没有生效的
这个也是后期需要解决的一个问题。
对模板更新的处理
目前项目中使用的是tpl的模板引擎。
现在就遇到一个问题,在热更新时,模板引擎其实是重复加载模板的,那么就涉及到重复加载是否后面的会覆盖前面问题。
查看加载模板的源码后,发现根据配置有三个选择,覆盖
,忽略
和报错
, 我们业务中使用的配置是遇到重复后会报错处理,所以我们需要在不修改业务默认属性的情况下,添加一些逻辑。
1 | // [esl-hot-update] 重新加载需要覆盖 |
window.EHU_HOT_UPDATE_OPTIONS.etpl.isOverride
这个是修改后自己实现的控制配置修改的逻辑。
然后这个文件加入到服务端的路由中,请求时替换。
对js更新的处理
这里逻辑比较复杂,因为需要修改底层的AMD模块加载的逻辑。
js没有模板那么简单,不是直接覆盖,因为在AMD模式中,每一个文件,都是被上一个文件调用执行的结果。
所以我们处理的逻辑是不仅需要重新加载修改的文件,并且递归所有直接或者间接调用他的文件,全部重新加载。
所以从上面的特点可以看出,这个工具目前阶段主要适用于业务模块的开发,因为业务的依赖不会特别深,对于dep中的核心文件修改,就不是很合适,一旦文件比较底层,热跟新是重新加载的模块也会非常多。
另外也有很多其他的坑,还在不断优化中。
总结
这次实践其实就是业务中遇到的问题(系统太庞大,调试太麻烦),如何解决问题,如何把解决的思路变成一个解决方案,分享给团队。
因为自己解决了,和形成一个解决方案还是有非常大的差别的,例如我们在形成方案的过程中,就尝试了很多新东西,踩了很多坑。
目前还有个坑就是chrome浏览器,调试的Source资源时,如果一个资源重复加载,内存中会更新,但是对应的资源没有更新,导致断点时,映射不对(断点失效),目前暂时的解决方案是,每次请求时添加时间戳,让Source映射的资源强制更新。这个可以正常断点,但是断点没有记忆功能(坑啊,因为文件变了)。