The Hot Module Replacement(HMR)俗稱熱模塊替換。主要用來當代碼產生變化後,能夠在不刷新遊覽器的狀況下對局部代碼塊進行替換更新。這在不少狀況下都頗有用,例如在處理彈出框時,使用HMR能夠及時的看到變化,若是用刷新遊覽器的方式會回到初始頁面。css
不少人使用過HMR殊不知道它是如何工做的,這裏會對HMR實現原理進行解析。html
HMR是Webpack的一個可選功能,若是想使用須要主動打開。react
須要經過webpack-dev-server方式來管理webpack(另外一種方式是CLI)webpack
HMR只能工做在實現了HMR API的loaders裏,例如:‘style-loader’,'react-hot-loader'web
HMR只能在開發環境中使用,由於HMR會在打包的js中添加了不少額外的代碼,而且webpack-dev-server也只用於開發環境。ajax
webpack會在打包的js中注入不少js庫來讓HMR工做,下圖展現了當一個文件發生變化是HMR是如何工做的。json
圖片顏色說明:app
紫色:發生改變的js或者css文件webpack-dev-server
橘色:發生變化的代碼塊說明,變化後的代碼塊內容ide
彩蘭色:項目代碼
綠色:webpack-dev-server相關的庫,有圖中能夠發現,webpack-dev-server主要負責server端和遊覽器端的通訊。
藍色:webpack核心和插件庫,由圖中能夠發現,server端代碼的監聽以及遊覽器端新代碼的替換都是由webpack的不一樣模塊處理。
紅色:react-loader或者style-loader等HMR庫
當監聽到文件發生變化時,webpack 使用HotModuleReplacementPlugin生成一個mainifest(一個json結構描述了發生變化的modules列表)和update file(一個js文件包含修改後的代碼內容)
webpack將上述變化信息告訴webpack-dev-server
webpack-dev-server經過webSocket給運行在遊覽器上的‘webpack-dev-server/client’(在打包時注入的js代碼)發送一條‘invalide’信息以及更新後代碼的hash值(該hash值本次不會用到,使用上一版本的hash值).
’webpack-dev-server/client’會將上一版本代碼的hash傳遞給「hot/dev-server」
‘hot/dev-server’使用JsonpRuntime向server端發送帶有上版本hash的ajax請求,server端返回一個json,該json包含要全部要更新的模塊的hash值。
JsonpRuntime根據返回的json值使用jsonp請求具體的代碼塊,jsonp返回的js代碼相似下面:
webpackHotUpdate(0,
{
82:
function(module, exports, __webpack_require__) {
exports = module.exports = __webpack_require__(79)();
exports.push([module.id, 「input {\n background: pink;\n}」, 「」])
}
})
代碼會調用webpackHotUpdate方法並攜帶module_id和具體修改內容。
HMR runtime自己並不會處理代碼修改,它會將不一樣文件交給對應的loader runtime處理(例如:react-hot-loader runtime 或者 style-loader runtime)
若是更新失敗,會回退刷新遊覽器獲取最新代碼。
當遊覽器首次加載app時,server端會推送當前代碼版本號current_hash。
當修改style文件後,server端HotModuleReplacementPlugin會根據更新內容生成manifest和js文件,文件名根據current_hash生成,而後更新current_hash,並將新的hash值推送給遊覽器端,用做下次更新。
遊覽器端webpack-dev-server/client接收到新的hash值後,會將previous hash值傳遞給webpack/hot/dev-server,dev-server根據previous hash請求具體的mainifest和js代碼,並使用jsonp更新。
參考文檔:
Webpack & The Hot Module Replacement
原文出處:https://www.cnblogs.com/chenkeyu/p/10801197.html