翻譯地粗糙, 英文好請直接看原文javascript
原文 https://github.com/webpack/docs/wiki/hot-module-replacement-with-webpackcss
注意模塊熱替換(HMR)依然是試驗性的功能html
模塊熱替換(HMR)交換, 添加, 或者刪除模塊, 同時應用持續運行, 不須要頁面刷新.java
使用插件: http://webpack.github.io/docs/using-plugins.htmlwebpack
webpack-dev-server: http://webpack.github.io/docs/webpack-dev-server.htmlgithub
App 代碼請求 HMR 運行時檢查更新.
HMR 運行時會下載(異步)更新的代碼, 通知 App 代碼運行已經可用.
App 代碼請求 HMR 運行時應用更新.
HMR 運行時應用更新(同步).
這個過程, App 代碼能夠也能夠不依賴用戶操做(看須要).web
除了普通的靜態文件, 編譯器觸發 "Update" 進行版本更新.
"Update" 包含兩個部分:npm
更對內容的 manifest (JSON)app
一個或者多個關於更新的 chunks (js)
manifest 包含新的編譯結果的 Hash 和列表儲存的 chunks (2.).
更新的 chunks 包含 chunk 當中全部更新掉的模塊的代碼
(或者模塊已經被移除的標記)
編譯器額外會保證模塊和 chunk 的 id 在多個建構當中一致
它使用 "records" JSON 文件在建構之間保存它們(或者存儲在內存裏)
HMR 是個可選功能, 它隻影響包含 HMR 代碼的模塊
文件裏描述了模塊中可用的 API
一般模塊開發者寫的處理器代碼會在這個模塊的依賴更新時被調用
他也能夠寫個處理器, 在當前模塊更新時被調用
大多數狀況不會強制在每一個模塊裏寫上 HMR 代碼
若是一個模塊不包含 HMR 處理器, 更新事件就會向上冒泡
意味着單個處理器能夠處理整個模塊樹的更新
若是樹當中單個模塊被更新, 整個模塊樹就會從新(刷新而不是 transferred(轉移?))
對模塊系統而言, 運行時意味着插入額外的代碼來追蹤模塊的父節點子節點
管理層面, 運行時支持兩個方法: check
和 apply
check
發起 HTTP 請求去獲取更新的 manifest
請求失敗時, 意味着沒有可用的更新
不然將能返回更新的 chunks 的列表, 和當前已加載的 chunks 列表作對比
每一個被更新的 chunk 對應的更新後的 chunk 都會被下載
全部存儲在運行時當中的代碼模塊隨着代碼進行更新
運行時會切換到 ready
狀態, 代表更新已經被下載並準備好應用
對於每一個 ready 狀態的新的 chunk 請求來講, 更新的 chunk 也已經被下載好了
apply
方法標記全部更新過的模塊爲 invalid
每一個 invalid 模塊須要有個 update 處理器, 在模塊中或者在每一個父節點
否則 invalid 向上冒泡, 多有的父節點也被標記爲 invalid
這個步驟持續知道再也不有"冒泡"出現
若是冒泡到了 entry point 就說明過程失敗了
如今全部 invalid 模塊會被處置(dispose 處理器)和卸載
隨後當前的 hash 被更新, 全部的 "accept" 處理器被調用
運行時切換回到 "idle" 狀態, 一切繼續正常運行
左側表示初始的編譯器流程
右側表示當模塊 4 和 9 更新的流程
你能夠在開發環境中用做 LiveReload 的替代
實際上 webpack-dev-server
支持一個 hot 狀態,
會嘗試先去經過 HMR 更新而後可能嘗試刷新整個頁面
你只須要加上一個 webpack/hot/dev-server
entry point,
而且在 dev-server
調用時加上參數 --hot
webpack/hot/dev-server
在 HMR 更新失敗以後會刷新整個頁面
若是你想本身刷新頁面, 能夠改用 webpack/hot/only-dev-server
這個 entry point.
你也能夠將其用做生產環境的更新機制
這裏你須要寫你本身的管理代碼集成 HMR 到你的應用當中
一些模塊已經能夠生成能夠完成熱替換的模塊
好比 style-loader
能夠替換樣式. 你不須要特別作事情
模塊只有在你的 "accept" 他的時候才能被更新
因此你須要在父節點或者父節點的父節點... module.hot.accept
調用模塊
好比 router 是個不錯的地方, 或者一個 subview 當中
若是你只是要和 webpack-dev-server
一塊兒用,
就加上 webpack/hot/dev-server
這個 entry point
否則你會須要一些 HMR 管理代碼去調用 check
和 apply
你須要在編譯器裏開啓 records 用來記錄不一樣過程的模塊 id
(watch 模塊和 webpack-dev-server
在內存裏追蹤 records
因此在開發當中你不須要作)
你須要開啓編譯器的 HMR 讓它加上 HMR 運行時
它是對於每一個模塊而言的 LiveReload
你能夠在生產環境使用
它依據你的代碼分割來更新, 只下載應用中須要更新的部分
你能夠用在應用的佈局, 不會影響到其餘的模塊
若是 HMR 被禁用, 全部的 HMR 代碼會被編譯器移除(包括在 if(module.hot)
中)
它屬於試驗性功能, 測試不夠
預計有一些 bug
理論上可用在生成環境, 然而在嚴肅的場合或許太早
模塊 id 須要在多個編譯過程被追蹤, 你須要存儲(records
)
優化器在第一次優化以後再也不可以優化模塊 id. 對 bundle 體積有影響
HMR 運行時增長了 bundle 的體積
生成環境須要額外的測試代碼檢驗 HMR 處理器. 挺難作的.
使用 Webpack 代碼熱替換須要作 4 件事:
records (--records-path
, recordsPath: ...
)
全局開啓代碼熱替換 (HotModuleReplacementPlugin
)
在你的代碼中插入熱替換代碼 module.hot.accept
在你的代碼中插入熱替換代碼 module.hot.check
, module.hot.apply
一個小測試:
/* style.css */ body { background: red; }
/* entry.js */ require("./style.css"); document.write("<input type='text' />");
這已經足夠在 dev-server
中使用代碼熱替換
npm install webpack webpack-dev-server -g npm install webpack css-loader style-loader webpack-dev-server ./entry --hot --inline --module-bind "css=style!css"
dev-server
提供內存裏的 records, 對開發來講很好
--hot
選項開啓了代碼熱替換.
這可以加上
HotModuleReplacementPlugin
. 若是使用命令行就不用寫到webpack.config.js
在 webpack/hot/dev-server
有 dev-server 特殊的管理代碼,
它會經過 --inline
自動加入.
(你不必定要在 webpack.config.js
里加上)
style-loader
已經包含了熱替換相關代碼.
隨後訪問 http://localhost:8080/bundle
的你應該能看到紅色背景和 input 框, 輸入些文字, 編輯下 style.css
改顏色
Voilà... 不須要刷新整個頁面, 背景更新了. 輸入框的文字和選區應該還在
閱讀更多關於怎樣寫本身的熱替換(管理)代碼 hot module replacement
訪問 example-app 直接查看 demo. (注意: 過期了, 也不要看源碼, 由於 HMR API 中間有修改)