Webpack打包后源碼分析

打包后的源碼分析

// /src/index.js
import name from './login'
console.log('index.js=[' + name + ']')
// /src/login.js
module.exports = "zce"
// dist/built.js
(function (modules) {
  // 01 定義對象用于將來緩存被加載過的模塊
  let installedModules = {}

  // 02 定義一個 __webpack_require__ 方法來替換 import require 加載操作
  function __webpack_require__(moduleId) {
    // 2-1 判斷當(dāng)前緩存中是否存在要被加載的模塊內(nèi)容执虹,如果存在則直接返回
    if (installedModules[moduleId]) {
      return installedModules[moduleId].exports
    }
    // 2-2 如果當(dāng)前緩存中不存在统刮,需要我們自己定義{} 執(zhí)行被導(dǎo)入的模塊內(nèi)容加載
    let module = installedModules[moduleId] = {
      i: moduleId,
      l: false,
      exports: {}
    }

    // 2-3 調(diào)用當(dāng)前 moduleId 對應(yīng)的函數(shù)福也,完成內(nèi)容的加載
    modules[moduleId].call(module.exports, module, module.exports, __webpack_require__)

    // 2-4 當(dāng)上述的方法調(diào)用完成之后此洲,我們就可以修改 l 的值用于表示當(dāng)前模塊內(nèi)容已經(jīng)加載完成了
    module.l = true;

    // 2-5 加載工作完成之后,要將拿回來的內(nèi)容返回至調(diào)用的位置
    return module.exports
  }

  // 03 定義 m 屬性用于保存 modules
  __webpack_require__.m = modules

  // 04 定義 c 用戶保存緩存 catch
  __webpack_require__.c = installedModules

  // 05 定義 o 方法判斷對象的身上是否存在指定的屬性
  __webpack_require__.o = function (object, property) {
    return Object.prototype.hasOwnProperty(object, property)
  }

  // 06 定義 d 方法用于在對象的身上添加指定的屬性,同時給該屬性提供一個 getter
  __webpack_require__.d = function (exports, name, getter) {
    if (!__webpack_require__.o(exports, name)) {
      Object.defineProperty(exports, name, { enumerable: true, get: getter })
    }
  }

  // 07 定義 r 方法 用于標(biāo)識當(dāng)前模塊是 es6
  __webpack_require__.r = function(exports) {
    if (typeof Symbol != 'undefined' && Symbol.toStringTag) {
      Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' })
    }
    Object.defineProperty(exports, '__esModule', { value: true })
  }

  // 08 定義 n 方法 用于設(shè)置具體的 getter
  __webpack_require__.n = function(module) {
    let getter = module && modules.__esModule ?
      function getDefault() { return module['default'] } : 
      function getmoduleExports() { return module }
    __webpack_require__.d(getter, 'a', getter)
  }

  // 09 定義 p 屬性胡控, 用于保存資源訪問路徑
  __webpack_require__.p = ""

  // 調(diào)用 __webpack_require__ 方法 執(zhí)行模塊 導(dǎo)入與加載操作
  return __webpack_require__(__webpack_require__.s = './src/index.js')

})
  ({
    "./src/index.js":
      (function (module, __webpack_exports__, __webpack_require__) {

        "use strict";
        __webpack_require__.r(__webpack_exports__);
        var _login_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./login.js */ "./src/login.js");
        console.log('index.js 執(zhí)行了')
        console.log(_login_js__WEBPACK_IMPORTED_MODULE_0__["default"], '<------')
        console.log(_login_js__WEBPACK_IMPORTED_MODULE_0__["age"], '<------')
      }),
    "./src/login.js":
      (function (module, __webpack_exports__, __webpack_require__) {
        "use strict";
        __webpack_require__.r(__webpack_exports__);
        __webpack_require__.d(__webpack_exports__, "age", function () { return age; });
        __webpack_exports__["default"] = ('小明是一個帥哥');
        const age = 40
      })

  })

如何實(shí)現(xiàn)的懶加載

  • import() 嗯可以實(shí)現(xiàn)指定模塊的懶加載操作
  • 當(dāng)前懶加載的核心原理就是 jsonp
  • t 方法可以針對于內(nèi)容進(jìn)行不同的處理(處理方式取決于傳入的數(shù)值 8 6 7 3 2 1)

t方法分析及實(shí)現(xiàn)

// 11 定義 t 方法,用于加載指定 value 的模塊內(nèi)容旁趟,之后對內(nèi)容進(jìn)行處理再返回
  __webpack_require__.t = function (value, mode) {
    // 01 加載 value 對應(yīng)的模塊內(nèi)容( value 一般就是模塊 id )昼激,第二個值 mode 是一個二進(jìn)制的數(shù)值
    // 02 t 方法內(nèi)部做的第一件事情就是調(diào)用自定義的 require 方法加載 value 對應(yīng)的模塊導(dǎo)出,
    //    加載之后的內(nèi)容又重新賦值給 value 變量
    // 03 當(dāng)獲取 到了這個 value 值之后余下的  8 4 ns 2 都是對當(dāng)前的內(nèi)容進(jìn)行加工處理锡搜,然后返回使用
    // 04 當(dāng) mode & 8 成立時直接將 value 返回 ( commonJS)
    // 05 當(dāng) mode & 4 成立時直接將 value 返回 ( esModule )
    // 06 如果上述條件都不成立橙困,還是要繼續(xù)處理 value, 定義一個 ns {}
    //    6-1 如果拿到的 value 是一個可以直接使用的內(nèi)容,例如是一個字符趾耕餐,將它掛載到 ns 的 default 屬性上
    //    6-2 如果拿到的 value 是一個對象凡傅,則調(diào)用 d 方法添加屬性和 getter 方法

    if (mode & 1) {
      value = __webpack_require__(value)
    }

    if (mode & 8) {  // 加載了可以直接返回使用的內(nèi)容  1 和 8 說明是一個commonjs內(nèi)容
      return value
    }

    if ((mode & 4) && typeof value === 'object' && value && value.__esModule) {
      return value
    }

    // 如果 8 和 4 都沒有成立則需要自定義 ns 來通過 default 屬性返回內(nèi)容
    let ns = Object.create(null)

    __webpack_require__.r(ns)

    Object.defineProperty(ns, 'default',  { enumerable: true, value: value })

    if (mode & 2 && typeof value !== 'string') {
      for (var key in value) {
        __webpack_require__.d(ns, key, function (key) {
          return value[key]
        }.bind(null, key))
      }
    }

    return ns
  }

tapable工作流程

  • 實(shí)例化 hook 注冊事件監(jiān)聽
  • 通過 hook 觸發(fā)事件監(jiān)聽
  • 執(zhí)行懶編譯生成的可執(zhí)行代碼

Hook 本質(zhì)是 tapbale 實(shí)例對象

  • Hook 執(zhí)行機(jī)制可分為同步和異步

Hook 執(zhí)行特點(diǎn)

  • Hook: 普通鉤子,監(jiān)聽器之間互相獨(dú)立不干擾
  • BailHook: 熔斷鉤子肠缔,某個監(jiān)聽返回非 undefined 時后續(xù)不執(zhí)行
  • WaterfallHook: 瀑布鉤子夏跷,上一個監(jiān)聽的返回值可傳遞至下一個
  • LoopHook: 循環(huán)鉤子,如果當(dāng)前未返回 false則一直執(zhí)行

tapable 庫同步鉤子

  • SyncHook
  • SyncBailHook
  • SyncWaterfallHook
  • SyncLoopHook

tapable 庫異步串行鉤子

  • AsyncSeriesHook
  • AsyncSeriesBailHook
  • AsyncSeriesWaterfallHook

tapable 庫異步并行鉤子

  • AsyncParalleHook
  • AsyncParalleBailHook

Ast 在線調(diào)試

astexplorer.net

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末明未,一起剝皮案震驚了整個濱河市槽华,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌趟妥,老刑警劉巖猫态,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異披摄,居然都是意外死亡懂鸵,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進(jìn)店門行疏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來匆光,“玉大人,你說我怎么就攤上這事酿联≈障ⅲ” “怎么了?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵贞让,是天一觀的道長周崭。 經(jīng)常有香客問我,道長喳张,這世上最難降的妖魔是什么续镇? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮销部,結(jié)果婚禮上摸航,老公的妹妹穿的比我還像新娘制跟。我一直安慰自己,他們只是感情好酱虎,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布雨膨。 她就那樣靜靜地躺著,像睡著了一般读串。 火紅的嫁衣襯著肌膚如雪聊记。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天恢暖,我揣著相機(jī)與錄音排监,去河邊找鬼。 笑死杰捂,一個胖子當(dāng)著我的面吹牛舆床,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播琼娘,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼峭弟,長吁一口氣:“原來是場噩夢啊……” “哼附鸽!你這毒婦竟也來了脱拼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤坷备,失蹤者是張志新(化名)和其女友劉穎熄浓,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體省撑,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡赌蔑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了竟秫。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片娃惯。...
    茶點(diǎn)故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖肥败,靈堂內(nèi)的尸體忽然破棺而出趾浅,到底是詐尸還是另有隱情,我是刑警寧澤馒稍,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布皿哨,位于F島的核電站,受9級特大地震影響纽谒,放射性物質(zhì)發(fā)生泄漏证膨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一鼓黔、第九天 我趴在偏房一處隱蔽的房頂上張望央勒。 院中可真熱鬧不见,春花似錦、人聲如沸订歪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽刷晋。三九已至盖高,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間眼虱,已是汗流浹背喻奥。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留捏悬,地道東北人撞蚕。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像过牙,于是被迫代替她去往敵國和親甥厦。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評論 2 355

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