Open gnosis23 opened 5 years ago
入门资料 3 里介绍了 webpack
+ webpack-dev-server
HMR 的原理,但是业务代码部分介绍的相对简单,看完了还是不会自己写代码。
我在下面简单描述下 HMR runtime
部分的流程,然后结合官方例子进行实战。
hotCheck():
hotApply():
对每个更新的模块进行依赖检查,找到所有需要修改的模块,进行标记:accepted,disposed,unaccepted 等等。这个过程是 冒泡 的,比如 A 依赖 B 依赖 C ,一旦 C 更新,可能会检查 B 和 A。
unaccepted
发生在更新的模块以及所有依赖它的模块里都没有 module.hot.accept
的情况下。
accepted
发生在更新的模块或者所有依赖它的模块里出现了 module.hot.accept
的情况下。
disposed
发生在更新的模块或者所有依赖它的模块里出现了 module.hot.dispose
的情况下。
如果有 unaccepted
的模块,直接刷新浏览器
否则先对所有 disposed
模块进行 dispose 操作,切记这里的 dispose 是对老的模块而言。
然后对所有的 accepted
模块进行 accept 操作
其他动作
var requestHandler = require("./handler.js");
var server = require("http").createServer();
server.on("request", requestHandler);
server.listen(8080);
// 下面也会立即执行
if(module.hot) {
// module.hot.accept 事件被保存的起来,不会立即执行。一旦 handler.js 更新就会调用
module.hot.accept("./handler.js", function() {
server.removeListener("request", requestHandler);
requestHandler = require("./handler.js");
server.on("request", requestHandler);
});
}
// addStyleTag(css: string) => HTMLStyleElement
var addStyleTag = require("./addStyleTag");
var element = addStyleTag(".rule { attr: name }");
module.exports = null;
// check if HMR is enabled
if(module.hot) {
// accept itself:accept可以不传参数
module.hot.accept();
// removeStyleTag(element: HTMLStyleElement) => void
var removeStyleTag = require("./removeStyleTag");
// dispose handler:当移除或更新自己时执行
// 常用于清历老模块的内容
module.hot.dispose(function() {
// revoke the side effect
removeStyleTag(element);
});
}
探索下热模块更新(以下简称 HMR )原理,主要偏重开发者所能控制的部分,原理部分尽量减小。
入门资源
什么是 HMR
想想看以前每次改变代码以后,需要手动刷新页面查看效果,非常低效。后来出现的 live reload 改变了一点,但是每次刷新原来页面的状态就全部丢失了。 HMR 是一种在运行时动态改变模块代码的技术,可以理解为模块范围内的 live reload,这样的好处时可以保留页面的状态。
怎么利用 HMR
那怎么写热更新部分的代码呢?
参照下一节
其他思路
每次都要这么写也太折腾人了,而且不能指望所有用户都对 HMR 有了解。
dva.js
就用了一个 babel 插件 来自动替我们处理这些事情。(很有局限性)