成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

webpack hot-module-replacement 原理&踩坑

elva / 1024人閱讀

摘要:原理踩坑起因最近在做框架的熱更新,記錄一下的原理和小坑。文件系統(tǒng)接收更改并通知。運(yùn)行時(shí)通過(guò)請(qǐng)求這些更新。類(lèi)似的問(wèn)題還有很多,事件綁定手動(dòng)插入并且沒(méi)有銷(xiāo)毀的定時(shí)器等,記得把這些副作用一起干掉。參考官方文檔原理分析與實(shí)現(xiàn)

webpack hot-module-replacement 原理&踩坑 起因

最近在做san框架的熱更新,記錄一下webpack HMR的原理和小坑。

什么是HMR?

熱更新是webpack的一個(gè)特性,通過(guò)無(wú)刷新實(shí)現(xiàn)代碼更新。

在HMR之前,大多數(shù)開(kāi)發(fā)體驗(yàn)是live reload,保存后自動(dòng)刷新瀏覽器,已經(jīng)是比刀耕火種的年代強(qiáng)很多了,但是自從某天在油管上看到dan神的redux時(shí)間穿梭,瞬間被驚艷到(當(dāng)然,HMR已經(jīng)是這之前很久就出現(xiàn)了)。

HMR大幅提高了開(kāi)發(fā)體驗(yàn),只更新變更內(nèi)容,調(diào)整樣式迅速,避免了大部分的網(wǎng)絡(luò)請(qǐng)求、瀏覽器重新渲染、app解析編譯顯示,讓我們來(lái)看下他是如何做到的。

hmr基本法

概念

compile: webpack的核心。js編譯、拆包。
hmr-server: 建立連接并完成模塊熱更新的推送。
bundle-server: 靜態(tài)服務(wù)器。
bundle.js: client端。
hmr-runtime: 注入到bundle.js中的代碼。

更新流程

熱更新開(kāi)啟后,當(dāng)webpack打包時(shí),會(huì)向client端注入一段HMR runtime代碼,同時(shí)server端(webpack-dev-server或是webpack-hot-middware)啟動(dòng)了一個(gè)HMR服務(wù)器,它通過(guò)websocket和注入的runtime進(jìn)行通信。

當(dāng)webpack檢測(cè)到文件修改后,會(huì)重新構(gòu)建,并通過(guò)ws向client端發(fā)送更新消息,瀏覽器通過(guò)jsonp拉取更新過(guò)的模塊,回調(diào)觸發(fā)模塊熱更新邏輯。

1.修改了一個(gè)或多個(gè)文件。
2.文件系統(tǒng)接收更改并通知Webpack。
3.Webpack重新編譯構(gòu)建一個(gè)或多個(gè)模塊,并通知HMR服務(wù)器進(jìn)行了更新。
4.HMR Server使用websockets通知HMR Runtime需要更新。HMR運(yùn)行時(shí)通過(guò)HTTP請(qǐng)求這些更新(jsonp)。
5.HMR運(yùn)行時(shí)替換更新中的模塊,如果確定這些模塊無(wú)法更新,則觸發(fā)整個(gè)頁(yè)面刷新(這是個(gè)大坑。。)。

觸發(fā)頁(yè)面刷新
// webpack/hot/dev-server
if(module.hot) {
    var lastHash;
    //__webpack_hash__是每次編譯的hash值是全局的
    //Only available with the HotModuleReplacementPlugin or the ExtendedAPIPlugin
    var upToDate = function upToDate() {
        return lastHash.indexOf(__webpack_hash__) >= 0;
    };
    var check = function check() {
   // check([autoApply], callback: (err: Error, outdatedModules: Module[]) => void
   // If autoApply is truthy the callback will be called with all modules that were disposed. apply() is automatically called with autoApply as options parameter.(傳入哪些代碼已經(jīng)被更新的模塊)
   //If autoApply is not set the callback will be called with all modules that will be disposed on apply(). (不是true那么傳入的是哪些需要被apply處理的模塊)
        module.hot.check(true).then(function(updatedModules) {
            //檢查所有要更新的模塊,如果沒(méi)有模塊要更新那么回調(diào)函數(shù)就是null
            if(!updatedModules) {
                console.warn("[HMR] Cannot find update. Need to do a full reload!");
                console.warn("[HMR] (Probably because of restarting the webpack-dev-server)");
                window.location.reload();
                return;
            }
            //如果還有更新
            if(!upToDate()) {
                check();
            }
            require("./log-apply-result")(updatedModules, updatedModules);
            //已經(jīng)被更新的模塊都是updatedModules
            if(upToDate()) {
                console.log("[HMR] App is up to date.");
            }

        }).catch(function(err) {
            var status = module.hot.status();
            //如果報(bào)錯(cuò)直接全局reload
            if(["abort", "fail"].indexOf(status) >= 0) {
                console.warn("[HMR] Cannot apply update. Need to do a full reload!");
                console.warn("[HMR] " + err.stack || err.message);
                window.location.reload();
            } else {
                console.warn("[HMR] Update failed: " + err.stack || err.message);
            }
        });
    };
    var hotEmitter = require("./emitter");
    //獲取MyEmitter對(duì)象
    hotEmitter.on("webpackHotUpdate", function(currentHash) {
        lastHash = currentHash;
        if(!upToDate() && module.hot.status() === "idle") {
            //調(diào)用module.hot.status方法獲取狀態(tài)
            console.log("[HMR] Checking for updates on the server...");
            check();
        }
    });
    console.log("[HMR] Waiting for update signal from WDS...");
} else {
    throw new Error("[HMR] Hot Module Replacement is disabled.");
}

正常情況下,hmr只會(huì)更新模塊,不會(huì)觸發(fā)頁(yè)面刷新。

但是當(dāng)bundle.js中的代碼拋出異常時(shí),如果開(kāi)發(fā)者沒(méi)有手動(dòng)接收并處理,這個(gè)錯(cuò)誤會(huì)冒泡到webpack-hmr-runtime中。

runtime接收error后會(huì)console.log一些信息并立即刷新,通常情況下是沒(méi)辦法看到那些log的,因?yàn)樘炝恕?/p>

// vue-hot-reload-api.js
// 不得不說(shuō),這個(gè)一開(kāi)始確實(shí)沒(méi)搞懂是為啥要包一層
// 自己實(shí)現(xiàn)的時(shí)候才知道,當(dāng)有error彈出時(shí)
// 如果不手動(dòng)這樣接住error,webpack會(huì)接到然后立即location.reload()
// 根本來(lái)不及看reload之前給出的提示
// 所以要手動(dòng)處理下error
function tryWrap (fn) {
  return function (id, arg) {
    try { fn(id, arg) } catch (e) {
      console.error(e)
      console.warn("Something went wrong during Vue component hot-reload. Full reload required.")
    }
  }
}

所以開(kāi)發(fā)者需要自定義一個(gè)類(lèi)似的高階函數(shù)手動(dòng)處理下錯(cuò)誤,防止看不到錯(cuò)誤信息而刷新。

副作用

模塊的熱更新是好事,但是老模塊仍然有可能在client端留下了痕跡。試想一個(gè)組件被熱更新后,如果不處理之前的組件,那么新老兩個(gè)組件都會(huì)在瀏覽器中出現(xiàn)。

所以別忘了在module.hot.accept中清除掉舊的組件。
類(lèi)似的問(wèn)題還有很多,事件綁定、手動(dòng)插入并且沒(méi)有銷(xiāo)毀的dom、定時(shí)器等,記得把這些副作用一起干掉。

如果做不到的話,老老實(shí)實(shí)刷新你的瀏覽器吧。

參考

webpack官方文檔

?Understanding Webpack HMR

webpack-dev-server原理分析與HMR實(shí)現(xiàn)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/84825.html

相關(guān)文章

  • Next.js踩坑入門(mén)系列(二)— 添加Antd && CSS

    摘要:踩坑入門(mén)系列一二添加三目錄重構(gòu)再談路由陸續(xù)更新個(gè)人對(duì)于腳手架的有一種執(zhí)念,如果搭建出來(lái)就是一個(gè)首頁(yè)標(biāo)簽跳轉(zhuǎn),實(shí)在不是我這個(gè)處女座的風(fēng)格,因此第二步我就想引用框架,相信很多使用的開(kāi)發(fā)者用的也都是這個(gè)框架吧。 Next.js踩坑入門(mén)系列 (一) Hello Next.js (二) 添加Antd && CSS (三) 目錄重構(gòu)&&再談路由 陸續(xù)更新... 個(gè)人對(duì)于腳手架的UI有一種執(zhí)...

    lifesimple 評(píng)論0 收藏0
  • 從基礎(chǔ)到實(shí)戰(zhàn) 手摸手帶你掌握新版Webpack4.0詳解 一起讀文檔

    摘要:構(gòu)建構(gòu)建就是把源代碼轉(zhuǎn)換成發(fā)布到線上的可執(zhí)行代碼,包括如下內(nèi)容。自動(dòng)刷新監(jiān)聽(tīng)本地源代碼的變化,自動(dòng)重新構(gòu)建刷新瀏覽器。自動(dòng)發(fā)布更新完代碼后,自動(dòng)構(gòu)建出線上發(fā)布代碼并傳輸給發(fā)布系統(tǒng)。將文件放入到項(xiàng)目中,在中新建一個(gè)放字體圖標(biāo)的文件夾。 項(xiàng)目地址 github.com/wudiufo/Web… 知識(shí)點(diǎn)概覽: Loader,HMR ,Create React App, Caching, Plug...

    王軍 評(píng)論0 收藏0
  • 數(shù)人云|關(guān)于Docker Swarm&K8S,幾大要素免踩坑

    摘要:結(jié)論得到了開(kāi)發(fā)者社區(qū)的廣泛認(rèn)可,盡管它的安裝過(guò)程非常艱難,之所以受到歡迎的原因很大程度取決于它提供的靈活性,以及良好的谷歌背景,而有一個(gè)小型的社區(qū),增長(zhǎng)略微緩慢。 數(shù)人云之前分享了《聊聊調(diào)度框架,K8S、Mesos、Swarm 一個(gè)都不能少》那么你是否仍在Docker和Kubernetes選擇上陷入了困擾?所以不要擔(dān)心,因?yàn)檫@也是很多人的苦惱,這兩者都是非常優(yōu)秀的容器服務(wù),至于那種更好...

    Rainie 評(píng)論0 收藏0
  • Vue-hot-reload-api 源碼解析

    摘要:源碼解析起因最近在搞框架的熱加載方案,自然是少不了向成熟的框架學(xué)習(xí)偷窺。這將銷(xiāo)毀并重建整個(gè)組件包括子組件。通過(guò)使用說(shuō)明可以看出,暴露的接口還是很清晰的,下面來(lái)看下具體源碼實(shí)現(xiàn)。 Vue-hot-reload-api 源碼解析 起因 最近在搞san框架的熱加載方案,自然是少不了向成熟的框架學(xué)習(xí)(偷窺ing)。熱加載方案基本也只是主流框架在做,且做的比較成熟,大部分應(yīng)用開(kāi)發(fā)者并不會(huì)接觸到這...

    DobbyKim 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<