Hot Module Replacement(如下簡稱 HMR)是 webpack 發展至今引入的最使人興奮的特性之一 ,當你對代碼進行修改並保存後,webpack 將對代碼從新打包,並將新的模塊發送到瀏覽器端,瀏覽器經過新的模塊替換老的模塊,這樣在不刷新瀏覽器的前提下就可以對應用進行更新。(注意不是瀏覽器刷新)。node
咱們只須要在webpack.config.js裏配置好devServe便可實現自動刷新,但並非HMR,以下:react
devServer: {
// 服務器根目錄
contentBase: path.join(__dirname, "./src"),
port: 3000,
//會把打包後的資源輸入到服務器根目錄 + publicPath
publicPath: "/",
},
複製代碼
下面咱們以 react 爲例子,大概講述一下如何實現HMR, 首先咱們理解一下他實現的原理,如圖:webpack
1.webpack監聽到文件的變化,進行新的編譯和打包,而且以簡單的js對象保存在內存中。web
2.webpack與devServer進行交互,告訴webpack要保存代碼到內存中。json
3.devServer對文件的監控,而且經過配置來告訴devServer是刷新仍是進行熱更新。瀏覽器
4.devServer經過sock.js和瀏覽器創建websock長連接,把webpack編譯代碼各階段信息告訴瀏覽器(包括更新模塊的hash),就是經過這一個hash來進行更新的。服務器
5.webpack經過devServer的配置和傳遞給他的信息(也就是第二部監聽的信息)來決定是否進行瀏覽器刷新或者熱更新。babel
6.webpack的HotModuleReplacement經過JsonpMainTemplate.runtime 向 server 端發送 Ajax 請求,服務端返回一個 json,該 json 包含了全部要更新的模塊的hash值,獲取到更新列表後,該模塊再次經過jsonp請求,獲取到最新的模塊代碼。這就是上圖中 七、八、9 步驟。webpack-dev-server
10.HotModulePlugin將會對新舊模塊進行對比,決定是否更新模塊,在決定更新模塊後,檢查模塊之間的依賴關係,更新模塊的同時更新模塊間的依賴引用。jsonp
11.當 HMR 失敗後,回退到 live reload 操做,刷新瀏覽器。
webpack.config.js配置以下:
devServer: {
// 服務器根目錄
contentBase: path.join(__dirname, "./src"),
port: 3000,
//會把打包後的資源輸入到服務器根目錄 + publicPath
publicPath: "/",
inline: true,
hot: true,
},
plugins: [
...
new webpack.HotModuleReplacementPlugin(),
]
複製代碼
入口文件配置
若是已經經過 HotModuleReplacementPlugin 啓用了模塊熱替換(Hot Module Replacement),則它的接口將被暴露在module.hot屬性下面。一般,用戶先要檢查這個接口是否可訪問,而後再開始使用它。 ——引自webpack官網
if (module.hot) {
module.hot.accept(() => {
ReactDom.render(
<App />, document.getElementById('root') ) }) } ReactDOM.render(<App />, document.getElementById("root")); 複製代碼
因爲熱更新並不會保存react的state狀態,因此咱們必須引用一個loader,react-hot-loader。
webpack.config.js配置
rules: [
...
{
test: /\.(js|jsx)$/,
exclude: /(node_modules|bower_components)/,
loader: "babel-loader",
options: {
presets: ["@babel/env"],
plugins: ["react-hot-loader/babel"] //增長
}
},
]
複製代碼
entry: [
'react-hot-loader/patch', //添加
"./src/index.js",
],
複製代碼
入口文件
if (module.hot) {
module.hot.accept(() => {
ReactDom.render(
<AppContainer> <App /> </AppContainer>,
document.getElementById('root')
)
})
}
ReactDOM.render(<App />, document.getElementById("root")); 複製代碼
##小結 webpack的HMR就到此爲止啦,參考文章: zhuanlan.zhihu.com/p/30669007