什么是浏览器的热更新
热更新是保存后⾃动编译(Auto Compile)吗?还是⾃动刷新浏览器(Live Reload)?还是指 HMR(Hot Module Replacement,模块热替换)?
浏览器的热更新,指的是我们在本地开发的同时打开浏览器进⾏预览,当代码⽂件发⽣变化时,浏览器⾃动更新⻚⾯内容的技术。这⾥的⾃动更新,表现上⼜分为⾃动刷新整个⻚⾯,以及⻚⾯整体⽆刷新⽽只更新⻚⾯的部分内容。
webpack 中的热更新配置
-
Watch 模式
webpack 中增加了 watch 模式,通过监控源码⽂件的变化来解决文件变化后不能⾃动编译问题。
当执⾏ npm run build:watch ,webpack 同样执⾏⼀次打包过程,但在打包结束后并未退出当前进程,⽽是继续监控源⽂件内容是否发⽣变化,当源⽂件发⽣变更后将再次执⾏该流程,直到⽤户主动退出(除了在配置⽂件中加⼊参数外,也可以在 webpack 命令中增加 --watch 来实现)。
有了 watch 模式之后,我们在开发时就不⽤每次⼿动执⾏打包脚本了。但是在浏览器⾥依然需要⼿动点击刷新才能看到变更后的效果。 -
Live Reload
为了使每次代码变更后浏览器中的预览⻚⾯能⾃动显示最新效果⽽⽆须⼿动点击刷新,我们需要⼀种通信机制来连接浏览器中的预览⻚⾯与本地监控代码变更的进程(路径前缀名为 /sockjs-node 的 websocket 链接)。
通过这个 websocket 链接,就可以使打开的⽹⻚和本地服务间建⽴持久化的通信。当源代码发⽣变更时,我们就可以通过 Socket 通知到⽹⻚端,⽹⻚端在接到通知后会⾃动触发⻚⾯刷新。 -
Hot Module Replacement(HMR,模块热替换)
在源码部分新增导⼊了⼀个简单的 CSS ⽂件,⽤于演示热替换的效果。在配置⽂件中,⾸先我们在 devServer 配置中新增了 hot:true ,其次,新增 module 的配置,使⽤ style-loader 和 css-loader 来解析导⼊的 CSS ⽂件。其中 cssloader 处理的是将导⼊的 CSS ⽂件转化为模块供后续 Loader 处理;⽽ style-loader 则是负责将 CSS 模块的内容在运⾏时添加到⻚⾯的 style 标签中。
当修改源码中 CSS 的样式后,⾸先在⽹络⾯板中,只是新增了两个请求:hot-update.json 和 hot-update.js ;其次,在审查元素⾯板中我们可以看到,在⻚⾯的头部新增了 hot-update.js ,并替换了原先 style 标签中的样式内容。
webpack 中的热更新原理
-
完整的 HMR 功能主要包含了三⽅⾯的技术:
- watch 示例中体现的,对本地源代码⽂件内容变更的监控。
- instant reload 示例中体现的,浏览器⽹⻚端与本地服务器端的 Websocket 通信。
- hmr 示例中体现的,也即是最核⼼的,模块解析与替换功能。
-
webpack 中的打包流程
解释⼏个 webpack 中的术语:- module:指在模块化编程中,我们把应⽤程序分割成的独⽴功能的代码模块。
- chunk:指模块间按照引⽤关系组合成的代码块,⼀个 chunk 中可以包含多个 module 。
- chunk group:指通过配置⼊⼝点(entry point)区分的块组,⼀个 chunk group 中可包含⼀到多个 chunk 。
- bundling:webpack 打包的过程。
- asset/bundle:打包产物。
webpack 的打包思想可以简化为 3 点:
- ⼀切源代码⽂件均可通过各种 Loader 转换为 JS 模块 (module),模块之间可以互相引⽤。
- webpack 通过⼊⼝点(entry point)递归处理各模块引⽤关系,最后输出为⼀个或多个产物包 js(bundle) ⽂件。
- 每⼀个⼊⼝点都是⼀个块组(chunk group),在不考虑分包的情况下,⼀个 chunk group 中只有⼀个 chunk ,该 chunk 包含递归分析后的所有模块。每⼀个 chunk 都有对应的⼀个打包后的输出⽂件(asset/bundle)。
-
原理
热替换的实现,既依赖 webpack 核⼼代码中 HotModuleReplacementPlugin 所提供的相关 API,也依赖在具体模块的加载器中实现相应 API 的更新替换逻辑。
因此,在配置中开启 hot:true 并不意味着任何代码的变更都能实现热替换,除了示例中演示的 style-loader 外, vue-loader 、 react-hot-loader 等加载器也都实现了该功能。
当开发时遇到 hmr 不⽣效的情况时,可以优先确认对应加载器是否⽀持该功能,以及是否使⽤了正确的配置。
网友评论