咱們在平常開發時,有一個須要在開發狀態下的優化,就是瀏覽器能自動顯示修改後的代碼,而無需咱們手動刷新javascript
1. 自動刷新瀏覽器
爲了能實現瀏覽器自動刷新,須要作兩件事情:java
1.1 監聽文件變化
監聽文件變化是在webpack模塊進行。node
1.1.1 方式
須要在webpack中開啓監聽模式,有兩種方式(開啓監聽模式後,能夠設置監聽相關配置watchOptions):webpack
1. 在webpack配置文件中添加watch:trueweb
module.export = {
watch: true,
watchOptions: {
// 不監聽的文件或文件夾
ignored: /node_modules/,
// 監聽到變化發生後會等300ms再去執行動做,防止文件更新太快致使從新編譯頻率過高
aggregateTimeout: 300,
// 判斷文件是否發生變化是經過不停的去詢問系統指定文件有沒有變化實現的
poll: 1000
}
}
2. 在執行啓動 Webpack 命令時,帶上 --watch 參數ajax
1.1.2 原理
- 在 Webpack 中監聽一個文件發生變化的原理是定時(可在watchOptions.poll中設置)的去獲取這個文件的最後編輯時間,每次都存下最新的最後編輯時間,若是發現當前獲取的和最後一次保存的最後編輯時間不一致,就認爲該文件發生了變化
- 當發現某個文件發生了變化時,並不會馬上告訴監聽者,而是先緩存起來,收集一段時間(可在watchOptions.aggregateTimeout中設置)的變化後,再一次性告訴監聽者。防止在編輯代碼的過程當中可能會高頻的輸入文字致使文件變化的事件高頻的發生
1.2 自動刷新瀏覽器
監聽到文件變化後須要去刷新瀏覽器,這部分在webpack-dev-server模塊中進行。(在使用 webpack-dev-server 模塊去啓動 webpack 模塊時,webpack 模塊的監聽模式默認會被開啓)api
1.2.1 原理
自動刷新有三種方法:瀏覽器
- 藉助瀏覽器擴展去經過瀏覽器提供的接口刷新
- 往要開發的網頁中注入代理客戶端代碼,經過代理客戶端去刷新整個頁面。
- 把要開發的網頁裝進一個 iframe 中,經過刷新 iframe 去看到最新效果。
DevServer 支持第二、3種方法,第2種是 DevServer 默認採用的刷新方法。緩存
2. 模塊熱更新
以上自動刷新是會刷新整個頁面,這種方式的缺點就是時間長,同時不能保存頁面的狀態。websocket
而模塊熱更新便可在不刷新整個頁面的狀況下來實時預覽。它只會在代碼發生變化時,只編譯發生變化的模塊,並替換瀏覽器中的老模塊。
2.1 兩種方式
如下兩種方式都能實現模塊熱替換,區別在於其內部使用的通訊方式不一樣。前者使用webcoket通訊,後者使用eventSource通訊。
2.1.1 webpack-dev-server
1. 開啓方式
- 開啓DevServer的模塊熱替換模式: webpack-dev-server --hot
- 添加HotModuleReplacementPlugin插件
2. 原理
參考
(1)webpack 對文件系統進行 watch 打包到內存中
- 依賴webpack-dev-middleware,它會調用 webpack 的 api 對文件系統 watch
- webpack-dev-middleware依賴memory-fs庫,它將webpack 本來的 outputFileSystem 替換成了MemoryFileSystem 實例,這樣代碼就將輸出到內存中
(2)devServer 通知瀏覽器端文件發生改變~~~~
- 在啓動 devServer 的時候,sockjs 在服務端和瀏覽器端創建了一個 webSocket 長鏈接。
- webpack-dev-server 調用 webpack api監聽 compile的 done 事件,將編譯打包後的新模塊 hash 值發送到瀏覽器端。
(3)webpack-dev-server/client 接收到服務端消息作出響應
- webpack-dev-server默認修改了webpack 配置中的 entry 屬性,在裏面添加了 webpack-dev-client 的代碼,這樣在最後的 bundle.js 文件中就會有接收 websocket 消息的代碼了。
- webpack-dev-server/client 當接收到 type 爲 hash 消息後會將 hash 值暫存起來,當接收到 type 爲 ok 的消息後對應用執行 reload 操做(根據 hot 配置決定是刷新瀏覽器仍是對代碼進行熱更新(HMR)).
(4)webpack 接收到最新 hash 值驗證並請求模塊代碼
- webpack/hot/dev-server監聽webpack-dev-server/client發出的webpackHotUpdate 消息。
- 先調用hotDownloadManifest(ajax請求)來獲取更新的文件列表。
- 再調用hotDownloadUpdateChunk獲取更新的新模塊代碼
(5)HotModuleReplacement.runtime 對模塊進行熱更新
- 找出過時的模塊和過時的依賴
- 從緩存中刪除過時的模塊和依賴
- 將新的模塊添加到 modules 中
2.1.2 webpack-hot-middleware
1. 開啓方式
- Webpack配置添加HotModuleReplacementPlugin插件
- Node Server引入webpack-dev-middlerware 和 webpack-hot-middleware插件(本人蔘與的項目中用到的是koa-webpack-middleware)
- entry中注入熱更新代碼(必需要注入。爲了保證服務端和客戶端可以通訊)
webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000
2. 原理
原理參考