Webpack 的運(yùn)行機(jī)制和核心工作原理
我們來(lái)解讀一下 Webpack 的運(yùn)行機(jī)制和核心工作原理。
其實(shí) Webpack 官網(wǎng)首屏的英雄區(qū)就已經(jīng)很清楚地描述了它的工作原理,如下圖所示:

我們以一個(gè)普通的前端項(xiàng)目為例,項(xiàng)目中一般都會(huì)散落著各種各樣的代碼及資源文件,如下圖所示:

比如 JS、CSS、圖片、字體等,這些文件在 Webpack 的思想中都屬于當(dāng)前項(xiàng)目中的一個(gè)模塊。Webpack 可以通過(guò)打包,將它們最終聚集到一起。
Webpack 在整個(gè)打包的過(guò)程中:
通過(guò) Loader 處理特殊類型資源的加載,例如加載樣式、圖片;
通過(guò) Plugin 實(shí)現(xiàn)各種自動(dòng)化的構(gòu)建任務(wù),例如自動(dòng)壓縮、自動(dòng)發(fā)布。
具體來(lái)看打包的過(guò)程。
Webpack 啟動(dòng)后,會(huì)根據(jù)我們的配置,找到項(xiàng)目中的某個(gè)指定文件(一般這個(gè)文件都會(huì)是一個(gè) JS 文件)作為入口。
然后順著入口文件中的代碼,根據(jù)代碼中出現(xiàn)的 import(ES Modules)或者是 require(CommonJS)之類的語(yǔ)句,解析推斷出來(lái)這個(gè)文件所依賴的資源模塊。
接著再分別去解析每個(gè)資源模塊的依賴,周而復(fù)始,最后形成整個(gè)項(xiàng)目中所有用到的文件之間的依賴關(guān)系樹(shù)。下面這個(gè)動(dòng)畫(huà)生動(dòng)的演示了這個(gè)過(guò)程:

有了這個(gè)依賴關(guān)系樹(shù)過(guò)后,Webpack 會(huì)遍歷(遞歸)這個(gè)依賴樹(shù),找到每個(gè)節(jié)點(diǎn)對(duì)應(yīng)的資源文件。
然后根據(jù)配置選項(xiàng)中的 Loader 配置,交給對(duì)應(yīng)的 Loader 去加載這個(gè)模塊。
最后將加載的結(jié)果放入 bundle.js(打包結(jié)果)中,從而實(shí)現(xiàn)整個(gè)項(xiàng)目的打包。
具體操作可以參考下面的動(dòng)畫(huà):

對(duì)于依賴模塊中無(wú)法通過(guò) JavaScript 代碼表示的資源模塊,例如圖片或字體文件,一般的 Loader 會(huì)將它們單獨(dú)作為資源文件拷貝到輸出目錄中,然后將這個(gè)資源文件所對(duì)應(yīng)的訪問(wèn)路徑作為這個(gè)模塊的導(dǎo)出成員暴露給外部。
整個(gè)打包過(guò)程中,Loader 機(jī)制起了很重要的作用。因?yàn)槿绻麤](méi)有 Loader 的話,Webpack 就無(wú)法實(shí)現(xiàn)各種各樣類型的資源文件加載,那 Webpack 也就只能算是一個(gè)用來(lái)合并 JS 模塊代碼的工具了。
至此,你就已經(jīng)了解到了 Webpack 的核心工作過(guò)程。
至于插件機(jī)制,只是 Webpack 為了提供一個(gè)強(qiáng)大的擴(kuò)展能力,它為整個(gè)工作過(guò)程的每個(gè)環(huán)節(jié)都預(yù)制了一個(gè)鉤子,它并不會(huì)影響 Webpack 的核心工作過(guò)程,也就是說(shuō)我們可以通過(guò)插件往 Webpack 工作過(guò)程的任意環(huán)節(jié)植入一些自定義的任務(wù),從而擴(kuò)展 Webpack 打包功能以外的能力。
推薦閱讀:
前端工程化中的重要環(huán)節(jié)——自動(dòng)化構(gòu)建
如何使用 Webpack 實(shí)現(xiàn)模塊化打包?
恭喜你又在前端道路上進(jìn)步了一點(diǎn)點(diǎn)。
點(diǎn)個(gè)“在看”和“贊”吧!
