webpack熱更新


首先要知道webpack-dev-server和webpack-dev-middleware這兩個依賴庫的主要區別。

webpack-dev-server主要負責項目的服務啟動和一些前置工作(比如生成webpack編譯主引擎(compile實例))。

webpack-dev-middleware主要提供的是本地文件操作方面相關的服務,比如文件的編譯,輸出(setFs())和監聽(compile.watch();

當執行npm start的時候:

  1. webpack-dev-server就開始生成編譯引擎(也就是compiler實例
  2. 生成完實例以后,緊接着啟動Server服務,而且可以看到,Server.js主要使用的是express框架
         
  3. 啟動了本地服務以后,又緊接着啟動了websocket服務
  4. Server.js還做了一件事情,就是修改了webpack.config.js的entry配置,主要實現的步驟是:
    1. 調用了updateCompiler方法,updateCompiler中又調用了addEntries方法,addEntries方法中有 2 段很關鍵的代碼
      1. addEntries方法執行以后,會改變entry入口的配置
      2. { entry:
            { index: 
                [
                    '../node_modules/webpack-dev-server/client/index.js',
                    '../node_modules/webpack/hot/dev-server.js',
                    './src/index.js'
            	],
            },
        }
      3. 新增websocket文件的原因,是因為上面的webpack-dev-server啟動的websocket服務目前服務端(webpack項目)代碼已經有了,但是瀏覽器的代碼還沒有,總不能webpack通知瀏覽器要更新代碼了,但是瀏覽器怎么接收消息並觸發更新事件呢?所以肯定要把這部分代碼給到瀏覽器。而第二個文件主要是用於檢查更新邏輯的
  5. Server.js調用了updateCompiler方法實現了入口文件配置的修改以后,又緊接着做了一件事,就是調用了setupHooks方法,這個方法主要是用來監聽每次webpack編譯完成的。
  6. 上面主要就是Server.js做的事情,下面看看文件的監聽是怎么做的
    1. 文件的監聽主要是在webpack-dev-middleware中做的
    2. 監聽文件的變化主要是通過文件的生成時間是否有變動來實現的。
  7. 現在,文件的監聽以及websocket通知已經做好了,下面看看瀏覽器收到通知以后具體做了哪些事情
    1. 剛才Server.js調用updateCompiler方法把websocket的客戶端代碼配置到了entry入口中,所以現在看看那段代碼做了什么
  8. 現在,Server.js通過updateCompiler方法添加到entry中的第一個文件作用已經說清楚了,添加的第二個文件,也就是webpack/hot/dev-server的作用還沒說
    1. 補充一點,check方法是是HotModuleReplacementPlugin插件搞的,把代碼注入到了bundle.js中
    2. check方法的源碼在webpack/lib/HotModuleReplacement.runtime.js(簡稱HMR runtime)中
    3. check方法中會利用 到webpack/lib/web/JsonpMainTemplate.runtime(簡稱Jsonp runtime)中的兩個方法hotDownloadManifest和hotDownloadUpdateChunk
      1. hotDownloadManifest的主要作用是發送{hash}.hot-update.json的ajax請求,獲取更新清單以及獲取下次熱更新的Hash 標識
      2. hotDownloadUpdateChunk主要作用是通過得到上面的更新清單去發送{hash}.hot-update.js 請求下載相應的更新塊,而且是通過JSONP的方式
  9. 通過上面一系列的文件監聽、socket通信、瀏覽器收到通信並請求到新文件這些操作以后,就看是如何進行熱更新的。打開hot-update.js文件以后,會發現一個webpackHotUpdate的方法。
    1. 源碼中這個方法有一個callback,會執行hotAddUpdateChunk方法,
    2. hotAddUpdateChunk接收兩個參數,一個是chunkId(對應hot-update.js響應體中的webpackHotUpdate函數中的“main”),一個是moreModules(對應hot-update.js響應體中的webpackHotUpdate函數中的那個對象);拿到需要更新的模塊以后,hotAddUpdateChunk會用for in的形式遍歷模塊對象,並且賦值給全局全量hotUpdate。然后執行hotUpdateDownloaded方法

    3. 來看下hotUpdateDownloaded做了什么事,當執行hotUpdateDownloaded的時候,也就意味着熱更新的前期工作已經全部做完了(webpack監聽變更文件、Browser請求變更文件、處理變更文件)。所以hotUpdateDownloaded會把runtime狀態置為“ready”,然后執行hotApply准備開始應用。
  10. 上面的所有的操作全部處於准備階段,接下的hotApply才是正式應用module到頁面中
    1. hotApply主要調用了hotApplyInternal這個方法。應用新模塊主要分為了三個階段
    2. 第一階段,找出所有過期的依賴和模塊
    3. 第二階段,刪除緩存中的依賴要替換的模塊,
    4. 將runtime的狀態置為“apply”並將新的模塊添加到modules中
  11. 到此,所有的新模塊已經全部在module中了,代碼下次調用__webpack_require__的時候,就是最新模塊


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM