在Webpack热替换(Hot Module Replacement,HMR)的过程中,主要涉及到以下几个环节:
- 文件修改:当你在本地编辑器中修改源代码并保存后,Webpack会监听到文件系统的变化。
- 重新编译:Webpack会对修改过的文件进行重新编译,并生成新的编译结果。这个过程中,Webpack会把修改的模块打包成一个新的热更新chunk。
- 热更新chunk生成:Webpack生成的热更新chunk包含了新旧模块之间的差异,以及这个更新的hash值。这个chunk会被发送到服务器。
- Webpack-dev-server:Webpack-dev-server监听到有新的编译结果后,会通过WebSocket通知浏览器有模块更新。
- 浏览器处理更新:浏览器收到更新通知后,会通过Webpack的HMR runtime请求热更新的chunk文件,然后用这个文件来更新内存中运行的应用代码。
- 应用代码更新:Webpack的HMR runtime会根据热更新chunk中的信息,用新的模块替换旧的模块。如果这个过程中没有发生错误,那么更新就完成了。如果发生了错误,那么可能需要进行页面刷新来恢复应用的状态。
在这个过程中,每个环节的输入和输出如下:
- 文件修改:输入是你修改的源代码,输出是修改后的源代码。
- 重新编译:输入是修改后的源代码,输出是编译结果,包括热更新chunk。
- 热更新chunk生成:输入是编译结果,输出是热更新chunk。
- Webpack-dev-server:输入是热更新chunk,输出是WebSocket通知。
- 浏览器处理更新:输入是WebSocket通知,输出是更新请求。
- 应用代码更新:输入是更新请求和热更新chunk,输出是更新后的应用代码。
如图所示:
如果你需要实现热更新(Hot Module Replacement,HMR)功能,即在不刷新浏览器的情况下替换、添加或删除模块,那么你需要使用 module.hot API。
Webpack 的 HMR 功能是通过 module.hot API 来实现的。module.hot API 提供了一些方法,如 accept、decline 等,用于控制模块的热替换行为。
需要注意的是,HMR 不是所有模块都可以使用的。一些特定类型的模块,如 CSS 模块,需要特定的 loader(例如 style-loader 或 css-loader)来支持 HMR。对于 JavaScript 模块,你需要确保你的代码是可接受热替换的,也就是说,你的代码需要能够在不刷新浏览器的情况下处理模块的更新。(eg:如果是react代码,则需要引入能够实现react-hot-replace的插件,否则更新react.tsx文件会导致浏览器刷新)
例如,你可以这样使用 module.hot API:
module.exports = {
test: function () {
console.log(33333)
}
}
import { test } from './page1.js'
document.write('hello sss~eeee')
// test()
if (module.hot) {
module.hot.accept(['./page1.js'], function() {
// 当 page1.js 更新时,这个函数会被调用
console.log('page1.js has been updated');
test() // 这里已经被替换
});
}
当引入的page1.js中的代码发生变化的时候,会执行module.hot中的accept代码。