App下載

webpack 構(gòu)建進(jìn)度條 ProgressPlugin 源碼剖析

猿友 2020-09-07 11:59:45 瀏覽數(shù) (5195)
反饋

文章轉(zhuǎn)載自公眾號:墨箏

前言

我們在使用 webpack 的時候經(jīng)常會用到 webpackbar 或者 progress-bar-webpack-plugin 之類的 webpack 插件通過進(jìn)度條等方式來展示 webpack 的構(gòu)建進(jìn)度,以提升構(gòu)建過程中的反饋體驗(yàn)。對于不同的插件來說,它們只是進(jìn)度條的 UI 展示形式不同而已,但最核心的 webpack 構(gòu)建的實(shí)時進(jìn)度的數(shù)據(jù)來源卻是一致的,均由 webpack 內(nèi)部的 ProgressPlugin 這個插件提供。下面我會結(jié)合源碼來講解該插件是如何計(jì)算 webpack 的構(gòu)建進(jìn)度并將進(jìn)度數(shù)據(jù)暴露給第三方的進(jìn)度條插件。在閱讀下文之前可以試著問下自己:如果是你,你會如何計(jì)算 webpack 的構(gòu)建進(jìn)度。

構(gòu)建進(jìn)度的計(jì)算

該插件主要根據(jù) webpack 的構(gòu)建階段來定義當(dāng)前進(jìn)度值。webpack 的構(gòu)建過程分為很多不同的階段,在每個階段 webpack 都暴露了對應(yīng)的事件鉤子。ProgressPlugin 正是通過這些事件鉤子對每個階段都定義了一個基礎(chǔ)進(jìn)度值,代碼如下所示:

webpack 構(gòu)建進(jìn)度條 ProgressPlugin 源碼剖析

上述代碼中的 interceptHook 方法可以先忽略,這個后續(xù)會提到。 通過上述代碼你會發(fā)現(xiàn) ProgressPlugincompiler 中的每個鉤子都設(shè)置了一個指定的進(jìn)度值。但這些進(jìn)度值還不夠細(xì)致到反映 webpack 的詳細(xì)構(gòu)建過程,中間還差了 0.06 到 0.69 以及 0.69 到 0.95 兩個階段的數(shù)值。webpack構(gòu)建的具體執(zhí)行過程主要在 compilation 中,這兩個階段的數(shù)值由 compilation 的鉤子填充。

0.06~0.69 webpack 構(gòu)建進(jìn)度條 ProgressPlugin 源碼剖析

update 方法的調(diào)用由 compilation 的鉤子觸發(fā),如下所示:

webpack 構(gòu)建進(jìn)度條 ProgressPlugin 源碼剖析

這個階段的主要工作是 module,entry 以及 dependencies 的處理和構(gòu)建。換個角度從 ProgressPlugin 給該階段設(shè)置的進(jìn)度值來看,這部分工作也是 webpack 最耗時的地方。

0.69~0.95 webpack 構(gòu)建進(jìn)度條 ProgressPlugin 源碼剖析

從上述代碼中可以看出這個間隔段就完全是根據(jù) compilation 的 hooks 來計(jì)算和指定當(dāng)前的構(gòu)建進(jìn)度值,從hook 的描述中可以看出這個階段主要是 module, chunk 以及assets等資源的優(yōu)化工作。 基本上整個 webpack 構(gòu)建過程的進(jìn)度值就是根據(jù)上述中的 compilercompilation 的 hooks 來設(shè)置的。

進(jìn)度數(shù)據(jù)的透出

webpack 的構(gòu)建進(jìn)度確定之后剩下的任務(wù)就是將進(jìn)度數(shù)據(jù)透出給第三方的進(jìn)度條插件進(jìn)行展示。要完成該任務(wù)需要ProgressPlugin完成兩件事情,一是提供回調(diào)函數(shù)的切入口;二是需要能在對應(yīng)的 hook 節(jié)點(diǎn)執(zhí)行該回調(diào)函數(shù)進(jìn)行進(jìn)度的百分比值的傳入。以下是這兩點(diǎn)的實(shí)現(xiàn)原理

回調(diào)函數(shù)

ProgressPlugin 定義了 handler 函數(shù)來作為回調(diào)函數(shù)切入,代碼如下所示:

webpack 構(gòu)建進(jìn)度條 ProgressPlugin 源碼剖析

hook 劫持

hook 劫持的實(shí)現(xiàn)非常簡單,主要利用 webpack hook 原生提供的intercept方法,前文中提到的interceptHook方法只是對于 intercept 方法的封裝,示例代碼如下:

webpack 構(gòu)建進(jìn)度條 ProgressPlugin 源碼剖析

結(jié)語

webpack 構(gòu)建的進(jìn)度條實(shí)現(xiàn)原理就是如此簡單,給每個構(gòu)建階段對應(yīng)的 hook 設(shè)置一個進(jìn)度值,然后通過 handler 回調(diào)和 hook 劫持切入到構(gòu)建環(huán)節(jié)將進(jìn)度信息傳入回調(diào)函數(shù),最終第三插件通過 handler 獲取到進(jìn)度值后將其展示出來。 webpack 的很多其他功能其實(shí)也沒有想象中的那么復(fù)雜和高大上,通過閱讀其源代碼了解其實(shí)現(xiàn)原理后,你很可能會一拍大腿,大嘆一聲原來如此,這本身就是一件挺有意思的事兒。

以上就是W3Cschool編程獅關(guān)于webpack 構(gòu)建進(jìn)度條 ProgressPlugin 源碼剖析的相關(guān)介紹了,希望對大家有所幫助。

0 人點(diǎn)贊