webpack的Hot Module Replacement運行機制

來源:互聯網
上載者:User

標籤:請求   ges   pre   一個   事件   ace   check   www   打包   

使用webpack打包,難免會使用Hot Module Replacement功能,該功能能夠實現修改、添加或刪除前端頁面中的模組代碼,而且是在頁面不重新整理的前提下。它究竟是怎麼運作的呢?本文主要從調試工具、設定檔、官方文檔三個方面進行解析。

調試工具

首先從chrome的調試工具network中看看,代碼改變的時候,頁面與後端之間發生了什嗎?

頁面初始載入

我們看到除了載入頁面所依賴的檔案外,多了一個串連,這是一個Server-sent Events,相關的介紹可以參考這篇文章,而且每隔一段時間都會向發送一次資料。資料內容主要是

action:sync操作;

hash:f397e485c539fd7a10fb,是bundle的hash,因為和產出檔案collections.f397e485c539fd7a10fbjs的內容hash值相同;

modules:產出bundle中的module id和對應的檔案地址。

 

 

修改代碼

然後修改一處代碼,webpack自動編譯後,發現network中發生了幾處變化,首先是用戶端收到後端發出的事件

action:built操作,通知瀏覽器webpack重新發起了編譯;

hash:最新產出bundle的內容hash值為debc36315df6764f157c;

modules:bundle中的模組id和對應模組的檔案地址。

另外前端對後端發起了兩個請求,請求了f397e485c539fd7a10fb.hot-update.json和0.f397e485c539fd7a10fb.hot-update.js兩個檔案,檔案的hash值正好是未發生修改之前後端發送前端的bundle hash值。

我們查看一下兩個檔案的內容。

json檔案的內容:

h:debc36315df6764f157c,bundle內容的最新hash值;

c:"0": true, 表示bundle id為0的檔案被修改了;

js檔案的內容:

內容是一個函數,類似jsonp的返回形式,也就是頁面收到請求後執行了webpackHotUpdate函數,對bundle id為0的檔案中的moudle id為50的模組進行修改。

跟進到這裡,我們可以推測出這個互動過程:

(0)webpack首次編譯時間將如何更新更新模組(update-method)和接收後端推動事件(event-source)的代碼打包到bundle之中;

(1)webpack進入watch 模式,在項目代碼發生變化的時候重新編譯;

(2)將編譯產出存放在dev-server,此處的編譯只針對變動的模組,產出應該包含上文中提到的oldbundlehash.hot-update.json和oldbundlehash.hot-update.js檔案;

(3)dev-server中使用hot-middleware中介軟體向前端發送built事件;

(4)前端收到通知後,向後端請求最新的變動檔案,請求到的js檔案通過script標籤載入後執行,其實就是執行已經預埋到bundle中的函數(update-method),從而修改bundle檔案。

 

 

設定檔 

接下來我們從項目的設定檔來驗證一下,設定檔主要參考vue-cli中的webapck項目。

webpack.dev.conf.js

涉及到Hot Module Replacement的地方主要有兩處:

entry的配置:在每個入口bundle開頭引入了event-source,即在頁面中接收後端發送的事件

/*********./build/webpack.dev.conf.js********/
// 將event-source相關代碼,添加到每個入口chunk中,作為HRM Runtime的一部分。// 後端相應的配置見dev-server的hotMiddleware部分Object.keys(baseWebpackConfig.entry).forEach(function (name) {    baseWebpackConfig.entry[name] = [‘./build/dev-client‘].concat(baseWebpackConfig.entry[name])})
/*********./build/dev-client.js********/// Event-Source對象用於接收伺服器端推送事件// eventsource-polyfill用於擴充Event-Source對象在IE瀏覽器下的相容性require(‘eventsource-polyfill‘)var hotClient = require(‘webpack-hot-middleware/client?noInfo=true&reload=true‘)// 主要用於接受後端hotMiddleware的通知,執行reload操作hotClient.subscribe(function (event) { if (event.action === ‘reload‘) { window.location.reload() }})

 

外掛程式的配置:引入HotModuleReplacementPlugin外掛程式,將update-method的代碼打入bundle

plugins: [        ...        // HMR外掛程式將HMR Runtime代碼嵌入到bundle中,能夠操作APP代碼,完成代碼替換        new webpack.HotModuleReplacementPlugin(),        // 報錯提示外掛程式:報錯不阻塞,但是編譯後給出提示        new webpack.NoEmitOnErrorsPlugin(),        new FriendlyErrorsPlugin()    ]
dev-server.js

涉及到Hot Module Replacement的地方主要有兩處:

將compiler掛載在devMiddleware上:對編譯產出提供靜態檔案服務

// 將compiler掛載在dev-server上,監聽本地代碼變化,變化則啟動編譯並將編譯後的檔案暫存到記憶體中var devMiddleware = require(‘webpack-dev-middleware‘)(compiler, {    publicPath: config.dev.assetsPublicPath === ‘./‘ ? ‘‘ : config.dev.assetsPublicPath,    quiet: true})

  

將compiler掛載在hotMiddleware上:通知前端event-source對象發生了rebuilt

// 編譯後發送通知到HRM Runtime,HRM Runtime收到update通知後,下載更新的模組,通知APP更新,APP收到通知,然後要求HRM Runtime執行模組替換var hotMiddleware = require(‘webpack-hot-middleware‘)(compiler, {    log: () => {}})

  

由設定檔可以基本驗證之前通過network debug得到的推論,接下來去看一下官方文檔驗證一下。

官方文檔

官方文檔先是總體介紹了一下 Hot Module Replacement的基本原理,然後將原理中涉及到幾個知識點進行了介紹。

基本原理

webapck在編譯的過程中,將HMR Runtime嵌入到bundle中;編譯結束後,webpack對項目代碼檔案進行監視,發現檔案變動重新編譯變動的模組,同時通知HMR Runtime,然後HMR Runtime載入變動的模組檔案,嘗試執行熱更新操作。更新的邏輯是:先檢查模組是否能支援accept方法,不支援的話,則冒泡尋找模組樹的父節點,直到入口模組,accept方法也就是模組hot-replace的handler。

知識點

(1)compiler

這裡的compiler也就是指webapck,主要提供update的資訊,也就是update menifest(json檔案格式)和update chunks(js檔案格式);

(2)app

app也就是指前端頁面,app中的代碼主要調用HMR Runtime下載最新的模組代碼,然後調用HMR Runtime執行update操作;

(3)HMR Runtime

HMR Runtime是webapck內嵌到前端頁面的代碼,主要提供來能給個職能check和apply。check用來下載最新模組代碼,runtime能夠接收後端發送的事件和發送請求;apply用於更新模組,主要將要更新的模組打上tag,然後調用模組的(也有可能是父模組)的更新handler執行更新。

(4)module

HRM是一個可插拔的工具,只能影響包含HMR code的模組。通常情況下,沒有必要為每個模組寫入HMR code,更新的時候會進行冒泡檢查HMR code的是否存在。

 

根據官方文檔的介紹,基本和我們的推論吻合,區別在於官方文檔引入了HMR Runtime的概念,這個可以看作是推論中的event-source和update-method的結合體。

現在大家應該清楚了 webpack的Hot Module Replacement的基本原理了,官方文檔中提到了如何根據最新的模組替換舊模組的方法,這個會放到下一篇文章中進行介紹。

webpack的Hot Module Replacement運行機制

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.