模塊支持熱替換(HMR)機(jī)制

webpack dev server自動(dòng)刷新問題:自動(dòng)刷新導(dǎo)致頁面狀態(tài)丟失

每次修改完代碼,webpack監(jiān)視到變化,自動(dòng)打包,并通過瀏覽器自動(dòng)刷新,一旦頁面整體刷新,頁面中的任何操作狀態(tài)都會(huì)丟失

HMR(Hot Module Replacement模塊熱替換)

”熱拔插“ 計(jì)算機(jī)正在運(yùn)行,插上去的設(shè)備可以立即工作,“熱"指在運(yùn)行過程中的即時(shí)變化

webpack模塊熱替換,實(shí)時(shí)的替換掉應(yīng)用中某個(gè)模塊,整體運(yùn)行狀態(tài)不會(huì)因此改變 例如上面的問題,使用HMR 就可以實(shí)現(xiàn)將修改的模塊實(shí)時(shí)替換到應(yīng)用中,不整體刷新

HMR是Webpack中最強(qiáng)大的功能之一,極大程度提高了開發(fā)者的工作效率

開啟HMR

兩種方式

  • 運(yùn)行命令webpack-dev-server --hot 開啟

  • 將devServer對(duì)象的hot屬性設(shè)置未true,然后需導(dǎo)入插件HotModuleReplacementPlugin

    const webpack = require('webpack')
    
    module.exports = {
      ...
        plugins: [
            ...
            new webpack.HotModuleReplacementPlugin()
        ]
    }
    

css文件熱更新正常 js文件熱更新頁面自動(dòng)刷新,狀態(tài)丟失

HMR疑問

HMR并不像webpack其他特性一樣開箱即用,需要額外操作(手動(dòng)通過代碼處理 當(dāng)模塊更新過后 如何把更新后模塊替換到頁面中)

  1. 為什么樣式文件熱更新?

    樣式文件經(jīng)過loader處理,在style-loader中已經(jīng)自動(dòng)處理了樣式文件的熱更新 不需要額外手動(dòng)處理

  2. 為什么腳本需要自己手動(dòng)處理?

    樣式文件更新后,只需把更新后的CSS及時(shí)替換到頁面中,覆蓋之前樣式,實(shí)現(xiàn)更新

    而JavaScript模塊沒有規(guī)律,可能導(dǎo)出對(duì)象、字符串或函數(shù),webpack面對(duì)毫無規(guī)律的JS模塊,不知道怎么處理更新后的模塊,也就無法直接實(shí)現(xiàn)一個(gè)可以通用所有情況的模塊替換方案

  3. 為什么vue-cli、create-react-app腳手架javaScript代碼會(huì)熱更新?

    框架中每個(gè)文件都有規(guī)律,例如react要求每個(gè)模塊導(dǎo)出必須是一個(gè)函數(shù)或類,這樣就有了通用的替換方法

HMR APIs

HotModuleReplacementPlugin提供一套處理HMR的API,使用這些API將更新后的模塊替換到正在運(yùn)行的頁面源代碼

// HMR 手動(dòng)處理模塊熱更新
// 不用擔(dān)心這些代碼在生產(chǎn)環(huán)境冗余的問題,因?yàn)橥ㄟ^ webpack 打包后,
// 這些代碼全部會(huì)被移除,這些只是開發(fā)階段用到
if (module.hot) {
  // HMR失敗后自動(dòng)回退到自動(dòng)刷新 頁面自動(dòng)刷新 控制臺(tái)的錯(cuò)誤信息會(huì)被清除
  let hotEditor = editor
  // 第一個(gè)參數(shù)接收的就是所監(jiān)視的依賴模塊路徑 第二個(gè)參數(shù)就是依賴模塊更新后的處理函數(shù)
  // editor.js更新被手動(dòng)處理后 就不會(huì)觸發(fā)自動(dòng)刷新
  module.hot.accept('./editor.js', () => {
    // 當(dāng) editor.js 更新,自動(dòng)執(zhí)行此函數(shù)
    // 臨時(shí)記錄編輯器內(nèi)容
    const value = hotEditor.innerHTML
    // 移除更新前的元素
    document.body.removeChild(hotEditor)
    // 創(chuàng)建新的編輯器
    // 此時(shí) createEditor 已經(jīng)是更新過后的函數(shù)了
    hotEditor = createEditor()
    // 還原編輯器內(nèi)容
    hotEditor.innerHTML = value
    // 追加到頁面
    document.body.appendChild(hotEditor)
  })

  module.hot.accept('./better.png', () => {
    // 當(dāng) better.png 更新后執(zhí)行
    // 重寫設(shè)置 src 會(huì)觸發(fā)圖片元素重新加載,從而局部更新圖片
    img.src = background
  })

  // style-loader 內(nèi)部自動(dòng)處理更新樣式,所以不需要手動(dòng)處理樣式模塊
}

注意

  1. 處理HMR的代碼報(bào)錯(cuò)會(huì)導(dǎo)致自動(dòng)刷新

    devServer: {
     // hot: true熱替換失敗就會(huì)自動(dòng)回退使用自動(dòng)刷新
        hotOnly: true hotOnly 的情況下并不會(huì)使用自動(dòng)刷新
    }                                           |
    
  2. 使用HMR提供的API,但啟動(dòng)webpsck-dev-serve時(shí)未開啟HMR

    // HMR 手動(dòng)處理模塊熱更新
    // 不用擔(dān)心這些代碼在生產(chǎn)環(huán)境冗余的問題,因?yàn)橥ㄟ^ webpack 打包后,
    // 這些代碼全部會(huì)被移除,這些只是開發(fā)階段用到
    if (module.hot) {
        ...
    }
    
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容