热更新 两个方面来看。
# 使用技术
以 vue 为例,我肯定不希望每当我更改代码时页面来一次刷新,我当然希望这个更改越小越好,如果我只改了一个组件,那么页面中也只应该更新这个组件(如果更改了路由配置啊,根配置啊,这种影响还是很难缩小的),在进一步,如果我只改了组件中的 js 或 template,那么此时应该保持视图/js 不变,不更新(这也是开发时文件中的 rerender 和 reveal 的逻辑) 2 拿 three 来说,诸如资源模块,时间模块等公有模块,大概率不会更改,一些会被重用的逻辑(如建一栋楼),大概率在开发的不同阶段需要少量更改,而具体的场景代码。大概率会随时更改,频繁更改
那我当然希望更改第二类模块时,第一类模块不重新加载,更改第三类时,第一第二类不重新加载,在进一步的话。如果场景划分区域,某区域代码更动,其他区域不受影响(可以接着推出第五类第六类模块,使得高层模块更改不影响低层模块)
具体实现来讲,就是该技术封装应该保留一些销毁重装部分模块的接口(取决于技术栈的具体情况)
# 打包工具
具体的逻辑就不说了,因为有些部分,比如浏览器持有资源清单这些,开发者很难直接操作。 反正其本质就是打包器持有一个 modulegraph,当文件更改时,打包工具通知浏览器更改范围,浏览器向服务器请求,从 modulegraph 中拿到需要的文件。这个过程中开发者可以介入的地方有三个,一是通知浏览器更改范围时,尽量缩小影响范围(实际上完全没必要,因为这种更新只能到文件级,打包工具这一块做的足够好了,如果要自研,还要禁止打包工具的自动通知,很麻烦),二是对 modulegraph 操作,也比较少见,性质上跟 webpack 的 loader 或 rollup 的 transform 差不多,(即在服务器中间件中偷偷更改 module,而这时候代码已经做了很大更改,尤其是 webpack,此时再更改往往会让问题更复杂),但如果某模块反复热更新失效,控制台表现却没有问题,那么大概率此时要到 modulegraph 这里看看情况
三是在前端代码中嵌入一些部分(当然只存在在开发时),这一部分能干这些事:保留部分数据,比如拖拽某个方块到了一个位置,结果一热更新,方块又被初始化到了原点, 如果有些数据想保留却做不到,那就要在热更新后尽力恢复它,比如 vue 中一个变量指向一个 dom,一次热更新后,dom 被卸载再挂载,此时原变量就找不到这个 dom 了
根据更改文件不同走不同的逻辑,比如此时收到的热更新信息指向 a 文件,我认为此时需要保留数据,就走保留的逻辑,但指向不是 a 文件的时候,就可以不做任何事,正常更新
大概就这些了,如果把这些都想过了,热更新仍然效果不好,那大概率是其他部分的问题。