国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Webpack 熱更新機(jī)制

mikasa / 1157人閱讀

摘要:聯(lián)想到我在微信小程序上的開發(fā)體驗(yàn),真心覺得如果有熱更新機(jī)制的話,開發(fā)效率要高很多。熱更新示例下面通過例子來進(jìn)一步解釋熱更新機(jī)制。

想必作為前端大佬的你,工作中應(yīng)該用過 webpack,并且對熱更新的特性也有了解。如果沒有,當(dāng)然也沒關(guān)系。

下面我要講的,是我對 Webpack 熱更新機(jī)制的一些認(rèn)識(shí)和理解,不足之處,歡迎指正。

首先:

熱更新是啥?

熱更新,是指 Hot Module Replacement,縮寫為 HMR

從名字上解讀,就是把“熱”的模塊進(jìn)行替換。熱,是指這個(gè)模塊已經(jīng)在運(yùn)行中。

不知道你有沒有聽過或看過這樣一段話:“在高速公路上將汽車引擎換成波音747飛機(jī)引擎”。

雖然有點(diǎn)牽強(qiáng),但是放在這里,從某些角度上來說,也還算合適吧。

再扯遠(yuǎn)一點(diǎn),說下我目前工作中的遇到的情況,相信很多人也遇到過。

微信小程序的開發(fā)工具,沒有提供類似 Webpack 熱更新的機(jī)制,所以在本地開發(fā)時(shí),每次修改了代碼,預(yù)覽頁面都會(huì)刷新,于是之前的路由跳轉(zhuǎn)狀態(tài)、表單中填入的數(shù)據(jù),都沒了。

哪怕只是一個(gè)文案或?qū)傩耘渲玫男薷模紩?huì)導(dǎo)致刷新,而要重新進(jìn)入特定頁面和狀態(tài),有時(shí)候很麻煩。對于開發(fā)時(shí)需要頻繁修改代碼的情況,這樣比較浪費(fèi)時(shí)間。

而如果有類似 Webpack 熱更新的機(jī)制存在,則是修改了代碼,不會(huì)導(dǎo)致刷新,而是保留現(xiàn)有的數(shù)據(jù)狀態(tài),只將模塊進(jìn)行更新替換。也就是說,既保留了現(xiàn)有的數(shù)據(jù)狀態(tài),又能看到代碼修改后的變化。

很美好,但是想想就覺得是一件肯定不簡單的事情。

所以,熱更新是啥呢?

引用官方文檔,熱更新是:

使得應(yīng)用在運(yùn)行狀態(tài)下,不重載刷新就能更新、增加、移除模塊的機(jī)制
熱更新解決的問題

那么熱更新要解決的問題,在上面也解釋了。用我的話來闡述,就是 在應(yīng)用程序的開發(fā)環(huán)境,方便開發(fā)人員在不刷新頁面的情況下,就能修改代碼,并且直觀地在頁面上看到變化的機(jī)制

簡單來說,就是為了 提升開發(fā)效率

聯(lián)想到我在微信小程序上的開發(fā)體驗(yàn),真心覺得如果有熱更新機(jī)制的話,開發(fā)效率要高很多。

如果你知道微信小程序已經(jīng)或計(jì)劃支持熱更新,或者有大佬已經(jīng)做了類似的工作,歡迎告訴我,感謝!

進(jìn)一步介紹前,我們來看下 Webpack 熱更新如何配置。

熱更新配置

如果你之前做的項(xiàng)目是其他人搭建配置了 Webpack 和熱更新,那么這里可以了解下熱更新是怎么配置的。

我的示例采用 Webpack 4,想直接看代碼的話,在這里:

https://github.com/luobotang/...

除了 Webpack,還需要 webpack-dev-server(或 webpack-dev-middleware)。

為 Webpack 開發(fā)環(huán)境開啟熱更新,要做兩件事:

使用 HotModuleReplacementPlugin 插件

打開 webpack-dev-server 的熱更新開關(guān)

HotModuleReplacementPlugin 插件是 Webpack 自帶的,在 webpack.config.js 加入就好:

// webpack.config.js
module.exports = {
  // ...
  plugins: [
    webpack.HotModuleReplacementPlugin(),
   // ...
  ]
}

如果直接通過 webpack-dev-server 啟動(dòng) Webpack 的開發(fā)環(huán)境,那么可以這樣打開 webpack-dev-server 的熱更新開關(guān):

// webpack.config.js
module.exports = {
  // ...
  devServer: {
    hot: true,
    // ...
  }
}

也很簡單。

熱更新示例

下面通過例子來進(jìn)一步解釋熱更新機(jī)制。如果你之前對 Webpack 熱更新的體驗(yàn),是 Vue 通過 vue-loader 提供給你的,也就是說你在自己的代碼中從沒有寫過或者見到過類似:

if (module.hot) {
  module.hot.accept(/* ... */)
  // ...
}

這樣的代碼,那么下面的例子就剛好適合看一看了。

這些例子就在上面的 webpack-hmr-demo,如果你對代碼更親切,那直接去看吧,首頁文檔里有簡單的說明。

示例1:沒有熱更新的情況

這個(gè)例子只是把示例頁面的功能簡單介紹下,并且讓你體會(huì)下每次修改代碼都要重新刷新頁面的痛苦。

頁面上只有一個(gè)元素,用來展示數(shù)值:

入口模塊(index.js)引用了兩個(gè)模塊:

timer.js:只提供了一個(gè) start 接口,傳入回調(diào)函數(shù),然后 timer 會(huì)間隔一段時(shí)間調(diào)用回調(diào)函數(shù),并傳入一個(gè)每次增加的數(shù)值

foo.js:沒啥功能,就簡單暴露一個(gè) message,引入它單純是區(qū)別 timer.js 展示不同的模塊更新處理方法

入口模塊的功能很簡單,調(diào)用 timer.start(),再傳入的回調(diào)函數(shù)中,每次將得到的數(shù)值更新到頁面上顯示:

import { start } from "./timer"
import { message } from "./foo"

var current = 0
var root = document.getElementById("root")
start(onUpdate, current)

console.log(message)

function onUpdate(i) {
  current = i
  root.textContent = "#" + i
}

將這個(gè)項(xiàng)目運(yùn)行起來,打開的頁面中就是在一直刷新展示增加的數(shù)值而已,類似這樣:

一旦修改任何模塊的代碼,例如改變 timer 中定時(shí)器的間隔時(shí)間(如從1秒改成3秒),或者 onUpdate 中展示的內(nèi)容(如 "#" + i 改成 "*" + i),頁面都會(huì)刷新,已經(jīng)有的狀態(tài)清除,重新從0開始計(jì)數(shù)。

示例2:處理依賴模塊的熱更新

接下來的例子,展示在 index.js 如何處理其他模塊的更新。

依賴的模塊發(fā)生更新,要么是接受變更(頁面不用刷新,模塊替換下就好),要么不接受(必須得刷新)。

Webpack 將熱更新相關(guān)接口以 module.hot 暴露到模塊中,在使用前,最好判斷下當(dāng)前的環(huán)境是否支持熱更新,也就是上面看到的這樣的代碼:

if (module.hot) {
  // ...
}

延續(xù)上一個(gè)例子,選擇接受并處理 timer 的更新,但對于 foo 模塊,不接受:

if (module.hot) {
  module.hot.accept("timer", () => {
    // ...
  })
  module.hot.decline("./foo")
}

所以,在熱更新的機(jī)制中,其實(shí)是以這種“聲明”的方式告知 Webpack,哪些模塊的更新是被處理的,哪些模塊的更新又不被處理。當(dāng)然對于要處理的模塊的更新,自行在 module.hot.accept() 的第二個(gè)參數(shù)即回調(diào)函數(shù)中進(jìn)行處理,會(huì)在聲明的模塊被替換后執(zhí)行。

下面來看對 timer 模塊更新的處理。

timer 模塊的 start 函數(shù)調(diào)用后返回一個(gè)可以終止定時(shí)器的 stop 函數(shù),借助它我們實(shí)現(xiàn)對舊的 timer 模塊的清理,并基于當(dāng)前狀態(tài)重新調(diào)用新的 timer 模塊的 start 函數(shù):

var stop = start(onUpdate, current) // 先記錄下返回的 stop 函數(shù)

// ...

if (module.hot) {
  module.hot.accept("timer", () => {
    stop()
    stop = start(onUpdate, current)
  })
  // ...
}

處理邏輯如上所述,先通過之前記錄的 stop 停止舊模塊的定時(shí)器,然后調(diào)用新模塊的 start 繼續(xù)計(jì)數(shù),并且傳入當(dāng)前數(shù)值從而不必從0開始重新計(jì)數(shù)。

看起來還是比較簡單的吧。運(yùn)行起來的效果是,如果修改 timer 中的定時(shí)器間隔時(shí)間,立即在頁面上就能看到效果,而且頁面并不會(huì)刷新導(dǎo)致重新從0開始計(jì)數(shù):

在運(yùn)行幾秒后,修改 timer 模塊中定時(shí)器的間隔時(shí)間為 100ms

修改 foo 中的 message,頁面還是會(huì)刷新。

有幾點(diǎn)額外說明下:

timer 模塊如果修改后不返回 start 接口,那么上述處理機(jī)制顯然會(huì)失效,所以這里的處理是基于模塊的接口不變的情況下

timer 模塊的 start 調(diào)用后顯然必須返回一個(gè) stop 函數(shù),否則在 index.js 是沒法清除 timer 模塊內(nèi)開啟的定時(shí)器的,這也很重要

或許你也注意到了,就是對 timer 模塊的 start 函數(shù)的引用貌似一直沒有變過,那為什么在回調(diào)函數(shù)中的 start 就是新模塊了呢?這個(gè)其實(shí)是有 Webpack 在編譯時(shí)處理掉的,編譯后的代碼并非當(dāng)前的樣式,對 start 會(huì)進(jìn)行替換,使得回調(diào)中的 start 一定引用到的是新的 timer 模塊的 start。感興趣可以看下 Webpack 文檔中對此的相關(guān)描述。

此外,除了聲明其他模塊更新的處理,模塊也可以聲明自身更新的處理,也是同樣的接口,不傳參數(shù)即可:

module.hot.accept() 告訴 Webpack,當(dāng)前模塊更新不用刷新

module.hot.decline() 告訴 Webpack,當(dāng)前模塊更新時(shí)一定要刷新

而且,依賴同一個(gè)模塊的不同模塊,可以有各自不同的聲明,這些聲明可能是沖突的,比如有的允許依賴模塊更新,有的不允許,Webpack 怎么協(xié)調(diào)這些呢?

Webpack 的實(shí)現(xiàn)機(jī)制有點(diǎn)類似 DOM 事件的冒泡機(jī)制,更新事件先由模塊自身處理,如果模塊自身沒有任何聲明,才會(huì)向上冒泡,檢查使用方是否有對該模塊更新的聲明,以此類推。如果最終入口模塊也沒有任何聲明,那么就刷新頁面了。這也就是為什么在上一個(gè)例子中,雖然開啟了熱更新,但是模塊修改后仍舊刷新頁面的原因,因?yàn)闆]有任何模塊對更新進(jìn)行處理。

示例3:處理自身模塊的熱更新

自身模塊的更新處理與依賴模塊類似,也是要通過 module.hot 的接口向 Webpack 聲明。不過模塊自身的更新,可能需要在模塊被 Webpack 替換之前就做一些處理,更新后的處理則不必通過特別接口來做,直接寫到新模塊代碼里面就好。

module.hot.dispose() 用于注冊當(dāng)前模塊被替換前的處理函數(shù),并且回調(diào)函數(shù)接收一個(gè) data 對象,可以向其寫入需要保存的數(shù)據(jù),這樣在新的模塊執(zhí)行時(shí)可以通過 module.hot.data 獲取到:

var current = 0
if (module.hot && module.hot.data) {
  current = module.hot.data.current
}

首先,模塊執(zhí)行時(shí),先檢查有沒有舊模塊留下來的數(shù)據(jù),如果有,就恢復(fù)。

然后在模塊被替換前的執(zhí)行處理,這里就是記錄數(shù)據(jù)、停掉現(xiàn)有的定時(shí)器:

if (module.hot)
  module.hot.accept()
  module.hot.dispose(data => {
    data.current = current
    stop()
  })
}

做了這些處理之后,修改 index.js 的 onUpdate,使得渲染到頁面的數(shù)值改變,也可以在不刷新的情況下體現(xiàn):

在運(yùn)行幾秒后,修改 onUpdate() 中的 "#" + i"*" + i
總結(jié)

看過上面的例子,我們來總結(jié)下。

Webpack 的熱更新,其實(shí)只是提供一套接口和基礎(chǔ)的模塊替換的實(shí)現(xiàn)。作為開發(fā)者,需要在代碼中通過熱更新接口(module.hot.xxx)向 Webpack 聲明依賴模塊和當(dāng)前模塊是否能夠更新,以及更新的前后進(jìn)行的處理。

如果接受更新,那么需要開發(fā)者自己來在模塊被替換前清理或保留必要的數(shù)據(jù)、狀態(tài),并在模塊被替換后恢復(fù)之前的數(shù)據(jù)、狀態(tài)。

當(dāng)然,像我們在使用 Vue 或 React 進(jìn)行開發(fā)時(shí),vue-loder 等插件已經(jīng)幫我們做了這些事情,并且對于 *.vue 文件在更新時(shí)要如果進(jìn)行處理,很多細(xì)節(jié)也只有 vue-loader 內(nèi)部比較清楚,我們就放心使用好了。

但是對于 Webpack 熱更新是怎么一回事,如果能夠有深入了解當(dāng)然更好,我就遇到過同事在 Vue 組件中自行對 DOM 進(jìn)行處理(為了封裝一個(gè)直接操作 DOM 的組件),結(jié)果由于熱更新的存在,導(dǎo)致一些狀態(tài)的清除有問題的情況。

這種情況,只有開發(fā)者自己才能處理,vue-loader 可沒法處理這樣的特殊情況。至少知道如何使用 Webpack 的熱更新接口,這種情況下開發(fā)者就能自行處理了。

本文對于 Webpack 熱更新機(jī)制的介紹還只是在接口使用的層面,或者大體的機(jī)制上,沒有深入說明熱更新的實(shí)現(xiàn)原理和細(xì)節(jié)。時(shí)間、篇幅有限,那就先放一張圖出來,或許有時(shí)間再細(xì)說一下。

上圖來源:

Webpack & The Hot Module Replacement
https://medium.com/@rajaraodv/webpack-hot-module-replacement-hmr-e756a726a07

這篇英文文章對 Webpack 熱更新實(shí)現(xiàn)原理方面有深入介紹。

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

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/100071.html

相關(guān)文章

  • Node.js 更新(一)

    摘要:直到最近在使用微信機(jī)器人時(shí),遇到了強(qiáng)烈的需求。增刪文件后熱更新上面的代碼已經(jīng)不小心實(shí)現(xiàn)了增加文件后熱更新,因?yàn)楸硎緳z測的更新,如果增加一個(gè),那么就變成,于是新模塊不等于老模塊不存在,從而使用注冊事件監(jiān)聽器。 背景 剛思考這個(gè)話題的時(shí)候,首先想到的是 Vue 或 React 的組件熱更新(基于 Webpack HMR),后來又想到了 Lua、Erlang 等語言的熱更新,不過在實(shí)際開發(fā) ...

    LancerComet 評(píng)論0 收藏0
  • 9102年:手寫一個(gè)React腳手架 【優(yōu)化極致版】

    摘要:馬上要出了,完全手寫一個(gè)優(yōu)化后的腳手架是不可或缺的技能。每個(gè)依賴項(xiàng)隨即被處理,最后輸出到稱之為的文件中,我們將在下一章節(jié)詳細(xì)討論這個(gè)過程。的事件流機(jī)制保證了插件的有序性,使得整個(gè)系統(tǒng)擴(kuò)展性很好。 webpack馬上要出5了,完全手寫一個(gè)優(yōu)化后的腳手架是不可或缺的技能。 本文書寫時(shí)間 2019年5月9日 , webpack版本 4.30.0最新版本 本人所有代碼均手寫,親自試驗(yàn)過可...

    Kylin_Mountain 評(píng)論0 收藏0
  • 9102年:手寫一個(gè)React腳手架 【優(yōu)化極致版】

    摘要:馬上要出了,完全手寫一個(gè)優(yōu)化后的腳手架是不可或缺的技能。每個(gè)依賴項(xiàng)隨即被處理,最后輸出到稱之為的文件中,我們將在下一章節(jié)詳細(xì)討論這個(gè)過程。的事件流機(jī)制保證了插件的有序性,使得整個(gè)系統(tǒng)擴(kuò)展性很好。 webpack馬上要出5了,完全手寫一個(gè)優(yōu)化后的腳手架是不可或缺的技能。 本文書寫時(shí)間 2019年5月9日 , webpack版本 4.30.0最新版本 本人所有代碼均手寫,親自試驗(yàn)過可...

    whatsns 評(píng)論0 收藏0
  • 9102年:手寫一個(gè)React腳手架 【優(yōu)化極致版】

    摘要:馬上要出了,完全手寫一個(gè)優(yōu)化后的腳手架是不可或缺的技能。每個(gè)依賴項(xiàng)隨即被處理,最后輸出到稱之為的文件中,我們將在下一章節(jié)詳細(xì)討論這個(gè)過程。的事件流機(jī)制保證了插件的有序性,使得整個(gè)系統(tǒng)擴(kuò)展性很好。 webpack馬上要出5了,完全手寫一個(gè)優(yōu)化后的腳手架是不可或缺的技能。 本文書寫時(shí)間 2019年5月9日 , webpack版本 4.30.0最新版本 本人所有代碼均手寫,親自試驗(yàn)過可...

    bingo 評(píng)論0 收藏0
  • webpack4大結(jié)局:加入騰訊IM配置策略,實(shí)現(xiàn)前端工程化環(huán)境極致優(yōu)化

    摘要:或者的,都會(huì)對其進(jìn)行分析。舒適的開發(fā)體驗(yàn),有助于提高我們的開發(fā)效率,優(yōu)化開發(fā)體驗(yàn)也至關(guān)重要組件熱刷新熱刷新自從推出熱刷新后,前端開發(fā)者在開環(huán)境下體驗(yàn)大幅提高。實(shí)現(xiàn)熱調(diào)試后,調(diào)試流程大幅縮短,和普通非直出模式調(diào)試體驗(yàn)保持一致。 showImg(https://segmentfault.com/img/bVbtOR3?w=1177&h=635); webpack,打包所有的資源 不知道不...

    李增田 評(píng)論0 收藏0

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

0條評(píng)論

mikasa

|高級(jí)講師

TA的文章

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