webpack热更新

230 阅读3分钟

在Webpack热替换(Hot Module Replacement,HMR)的过程中,主要涉及到以下几个环节:

  1. 文件修改:当你在本地编辑器中修改源代码并保存后,Webpack会监听到文件系统的变化。
  2. 重新编译:Webpack会对修改过的文件进行重新编译,并生成新的编译结果。这个过程中,Webpack会把修改的模块打包成一个新的热更新chunk。
  3. 热更新chunk生成:Webpack生成的热更新chunk包含了新旧模块之间的差异,以及这个更新的hash值。这个chunk会被发送到服务器。
  4. Webpack-dev-server:Webpack-dev-server监听到有新的编译结果后,会通过WebSocket通知浏览器有模块更新。
  5. 浏览器处理更新:浏览器收到更新通知后,会通过Webpack的HMR runtime请求热更新的chunk文件,然后用这个文件来更新内存中运行的应用代码。
  6. 应用代码更新: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 提供了一些方法,如 acceptdecline 等,用于控制模块的热替换行为。

需要注意的是,HMR 不是所有模块都可以使用的。一些特定类型的模块,如 CSS 模块,需要特定的 loader(例如 style-loadercss-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代码。