webpack源碼淺析并手寫一個(gè)打包工具

webpack工作流程

先祭出之前畫的webpack工作流程圖


webpack工作流程.png

源碼分析

webpack源碼很多谆构,看著看著就被各種類虾攻、設(shè)計(jì)模式繞暈了铡买。所以這篇文章會(huì)以webpack的打包流程為主線,分析每個(gè)環(huán)節(jié)的代碼所在的位置霎箍、大致做了哪些事情奇钞。

1.執(zhí)行webpack命令

一般來說我們都會(huì)在項(xiàng)目的package.json中配置一條打包命令,如:

"build": "node_modules/.bin/webpack --config webpack.prod.js",

當(dāng)我們執(zhí)行npm run build后漂坏,先會(huì)執(zhí)行bin/webpack.js這個(gè)文件景埃,內(nèi)部會(huì)執(zhí)行l(wèi)ib/webpack.js這個(gè)文件媒至。

2.初始化參數(shù)

在webpack.js中,會(huì)讀取初始參數(shù)并校驗(yàn)

const webpack = (options, callback) => {
    const webpackOptionsValidationErrors = validateSchema(
        webpackOptionsSchema,
        options
    );
    if (webpackOptionsValidationErrors.length) {
        throw new WebpackOptionsValidationError(webpackOptionsValidationErrors);
    }
    // ...
};

webpack函數(shù)的options參數(shù)就是我們命令中配置的webpack.prod.js這個(gè)文件的內(nèi)容谷徙,webpack拿到數(shù)據(jù)后會(huì)利用webpackOptionsSchema進(jìn)行json數(shù)據(jù)內(nèi)容的校驗(yàn)拒啰。

3.確定編譯入口文件

編譯前webpack會(huì)先注冊(cè)內(nèi)部、外部插件完慧;
其中內(nèi)部插件在WebpackOptionsApply.js中注冊(cè)图呢,然后會(huì)觸發(fā)相應(yīng)的hook調(diào)用EntryOptionPlugin插件;
通過entry插件程序開始從入口文件編譯骗随。

4.編譯文件

編譯時(shí)會(huì)用到compilation(編譯對(duì)象)蛤织,調(diào)用它的_addModuleChain從入口進(jìn)行編譯,它會(huì)利用moduleFactory將文件構(gòu)建成module如NormalModule鸿染;
接著調(diào)用module的build方法編譯當(dāng)前模塊指蚜;
最后找到模塊的依賴模塊并循環(huán)構(gòu)建這些依賴形成遞歸;
說明:
module的build方法會(huì)先使用匹配到的loaders進(jìn)行代碼轉(zhuǎn)換涨椒,然后交給Parser.js模塊摊鸡;
Parser利用acron解析module的抽象語法樹,然后walk出模塊的所有dependencies并將其設(shè)置在module中蚕冬。

5.輸出資源

執(zhí)行完編譯文件階段后免猾,我們得到了一棵根結(jié)點(diǎn)為入口模塊的依賴樹,并且樹上的結(jié)點(diǎn)都是經(jīng)過編譯的囤热;
最后調(diào)用compilation.seal將這棵樹上的代碼打包至一個(gè)bundle.js文件中猎提。

bundle文件大致結(jié)構(gòu)

(function (modules) {

  var installedModules = {};

  function __webpack_require__(moduleId) {}

  // Load entry module and return exports
  return __webpack_require__(0);

})(
  [
    function (module, __webpack_exports__, __webpack_require__) {
      console.log('module1');
    },
    function (module, __webpack_exports__, __webpack_require__) {
      console.log('module2');
    }
  ]
)

bundle文件中定義了一個(gè)自執(zhí)行函數(shù),然后調(diào)用這個(gè)函數(shù)傳遞了一個(gè)數(shù)組作為參數(shù)旁蔼,數(shù)組中的每一項(xiàng)都是打包后的模塊代碼锨苏;
自執(zhí)行函數(shù)中有一個(gè)installedModules對(duì)象緩存已加載的模塊,還有一個(gè)__webpack_require__是加載模塊的方法棺聊,最后加載了模塊0也就是我們的入口模塊作為業(yè)務(wù)程序的開始伞租。

手寫一個(gè)打包工具

git地址:https://github.com/shejiJiang/mini-webpack
最后我參考webpack的打包流程,手寫了一個(gè)簡單的打包工具限佩。拋棄了webpack的一堆概念葵诈,把打包流程代碼全寫在了lib/webpack.js文件中;
在webpack.js定義了一個(gè)打包方法祟同,會(huì)調(diào)用buildModule方法從入口開始編譯模塊作喘,然后調(diào)用bundle方法進(jìn)行打包,最后調(diào)用output輸出耐亏;
其中buildModule是一個(gè)遞歸執(zhí)行的過程徊都,它會(huì)先利用@babel/parser解析ast沪斟,再利用@babel/core編譯代碼广辰,然后利用@babel/traverse找到模塊的依賴暇矫,最后對(duì)每個(gè)依賴模塊遞歸執(zhí)行buildModule進(jìn)行編譯。

參考項(xiàng)目:https://github.com/ronami/minipack

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末择吊,一起剝皮案震驚了整個(gè)濱河市李根,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌几睛,老刑警劉巖房轿,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異所森,居然都是意外死亡囱持,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門焕济,熙熙樓的掌柜王于貴愁眉苦臉地迎上來纷妆,“玉大人,你說我怎么就攤上這事晴弃⊙诖保” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵上鞠,是天一觀的道長际邻。 經(jīng)常有香客問我,道長芍阎,這世上最難降的妖魔是什么世曾? 我笑而不...
    開封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮谴咸,結(jié)果婚禮上度硝,老公的妹妹穿的比我還像新娘。我一直安慰自己寿冕,他們只是感情好蕊程,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著驼唱,像睡著了一般藻茂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上玫恳,一...
    開封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天辨赐,我揣著相機(jī)與錄音,去河邊找鬼京办。 笑死掀序,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的惭婿。 我是一名探鬼主播不恭,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼叶雹,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了换吧?” 一聲冷哼從身側(cè)響起折晦,我...
    開封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎沾瓦,沒想到半個(gè)月后满着,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡贯莺,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年风喇,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片缕探。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡响驴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出撕蔼,到底是詐尸還是另有隱情豁鲤,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布鲸沮,位于F島的核電站琳骡,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏讼溺。R本人自食惡果不足惜楣号,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望怒坯。 院中可真熱鬧炫狱,春花似錦、人聲如沸剔猿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽归敬。三九已至酷含,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間汪茧,已是汗流浹背椅亚。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留舱污,地道東北人呀舔。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像扩灯,于是被迫代替她去往敵國和親媚赖。 傳聞我的和親對(duì)象是個(gè)殘疾皇子霜瘪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 在現(xiàn)在的前端開發(fā)中,前后端分離省古、模塊化開發(fā)、版本控制丧失、文件合并與壓縮豺妓、mock數(shù)據(jù)等等一些原本后端的思想開始...
    Charlot閱讀 5,433評(píng)論 1 32
  • 寫在開頭 先說說為什么要寫這篇文章, 最初的原因是組里的小朋友們看了webpack文檔后, 表情都是這樣的: (摘...
    Lefter閱讀 5,276評(píng)論 4 31
  • 記得2004年的時(shí)候,互聯(lián)網(wǎng)開發(fā)就是做網(wǎng)頁布讹,那時(shí)也沒有前端和后端的區(qū)分琳拭,有時(shí)一個(gè)網(wǎng)站就是一些純靜態(tài)的html,通過...
    陽陽陽一堆陽閱讀 3,275評(píng)論 0 5
  • 目錄第1章 webpack簡介 11.1 webpack是什么描验? 11.2 官網(wǎng)地址 21.3 為什么使用 web...
    lemonzoey閱讀 1,731評(píng)論 0 1
  • 互聯(lián)網(wǎng)經(jīng)過了李某星事件之后白嘁,雖然在一定程度上加強(qiáng)了監(jiān)管力度,但并沒有完全根除傳銷的影響膘流,傳銷依然活躍在互聯(lián)網(wǎng)上絮缅。在...
    我在你家哦閱讀 202評(píng)論 0 0