<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Webpack模塊化原理圖解

          共 3361字,需瀏覽 7分鐘

           ·

          2021-03-04 10:12

          為什么需要模塊化
          場(chǎng)景1
          A同學(xué)開發(fā)了模塊a,B同學(xué)開發(fā)了模塊b,在頁面下通過如下方式進(jìn)行引用
          <script src="a.js"></script><script src="b.js"></script>

          這時(shí)模塊a,模板b中的代碼都暴露在全局環(huán)境中,如果模塊a中定義了一個(gè)方法del。同學(xué)b并不知道,在模塊b中也定義了一個(gè)方法del。這時(shí)便造成了命名沖突的的問題。如圖


          場(chǎng)景2

          C同學(xué)開發(fā)了一個(gè)公共的工具庫utils.js,D同學(xué)開發(fā)了一個(gè)公共的組件tab.js,tab.js依賴utils.js。同學(xué)E需要使用D同學(xué)開發(fā)的tab.js,就需要通過如下方式引用

          <script src="util.js"></script><script src="tab.js"></script>

          同學(xué)E自己也開發(fā)了一個(gè)dailog.js同時(shí)它也依賴util.js。現(xiàn)在頁面同時(shí)引用了dialog.js和tab.js,代碼如下。

          <script src="util.js"></script><script src="dialog.js"></script><scrpt src="tab.js"></script>

          同學(xué)E不僅需要同時(shí)引用這三個(gè)js文件,還必須保證文件之間的引用順序是正確的。同時(shí),從上面的代碼我們無法直接看出模塊與模塊之間的依賴關(guān)系,如果不深入tab.js,我們無法知道tab.js到底是只依賴util.js還是dialog.js或者兩者都依賴。隨著項(xiàng)目逐漸增大,不同模塊之間的依賴關(guān)系則會(huì)變的越來越難以維護(hù)也會(huì)導(dǎo)致許多模塊中大量的變量都暴露在全局環(huán)境中。

          模塊化的幾種實(shí)現(xiàn)方案

          模塊化的規(guī)范有很多種, 如下
          | 規(guī)范 | 實(shí)現(xiàn)方案 |
          | --- | --- |
          | CommonJS | node.js |
          | AMD | Require.js |
          | CMD | Sea.js
          | UMD | |
          | ES6 Module | |

          webpack支持CommonJS,AMD,ESModule等多種模塊化方式的語法。

          webpack的模塊化原理

          在webpack中,一切皆模塊。下面我們通過webpack來打包以下代碼。通過對(duì)打包代碼的解析,來一步一步的了解模塊化的實(shí)現(xiàn)原理。

          目錄結(jié)構(gòu)如下:


          代碼如下:

          // webpack.config.jsconst path = require('path');
          module.exports = { entry: 'a.js', output: { path: path.resolve(__dirname, "dist"), filename: "[name].js" }, resolve: { modules: [path.resolve(__dirname)] }, optimization: { minimize: false }}// a.jsvar b = require('b');
          module.exports = b.text + ' world';// b.jsexports.text = 'hello';

          在simple目錄下執(zhí)行webpack命令,會(huì)在simple目錄下生成dist/output.js文件。

          // outout.js// 代碼及注釋如下
          (() => { // 所有導(dǎo)入的模塊都存儲(chǔ)在__webpack_modules__對(duì)象中,并且每個(gè)模塊都要一個(gè)標(biāo)識(shí)該模塊的id var __webpack_modules__ = ({ 847: ((module, __unsed_webpack_exports, __webpack_require__) => { // 模塊a... }), 996: ((__unused_webpack_module, exports) => { // 模塊b... }) })
          var __webpack_module_cache__ = {};
          function __webpack_require__(moduleId) { // 檢查緩存中不存在847導(dǎo)出對(duì)象,防止模塊847多次執(zhí)行 if (__webpack_module_cache__[moduleId]) { // 從緩存中返回847導(dǎo)出對(duì)象 return __webpack_module_cache__[moduleId].exports; }
          // 1.創(chuàng)建{exports: {}}對(duì)象 // 2.像緩存中添加該對(duì)象,并讓該對(duì)象與模塊id 847相關(guān)聯(lián) var module = __webpack_module_cache__[moduleId] = { exports: {} }
          // 3.通過__webpack_modules__查詢模塊847 // 4.執(zhí)行模塊847并傳入剛剛創(chuàng)建的模塊847的導(dǎo)出對(duì)象module,以及module.exports等 __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
          // 5.返回模塊847的導(dǎo)出對(duì)象 return module.exports; }
          // 導(dǎo)入模塊847 __webpack_require__(847);})()
          如上代碼我們可以知道,所有的的模塊都存儲(chǔ)在__webpack_modules__對(duì)象中,模塊的導(dǎo)出對(duì)象則存儲(chǔ)在__webpack_module_cache__對(duì)象中,我們定義的模塊都可以通過傳入moduleId來調(diào)用__webpack_require__接口來訪問該模塊以及該模塊的導(dǎo)出對(duì)象。
          當(dāng)我們通過__webpack_require__接口訪問模塊847的導(dǎo)出對(duì)象時(shí)。會(huì)先判斷__webpack_module_cache__對(duì)象中有沒有該模塊的導(dǎo)出對(duì)象,如果有的話,則直接返回。如果沒有的話則會(huì)
          (1)創(chuàng)建模塊847的導(dǎo)出對(duì)象
          var module = {  exports: {}}

          (2)將該導(dǎo)出對(duì)象添加到__webpack_module_cache__對(duì)象中

          __webpack_module_cahce__[moduleId] = module

          (3)(4)通過__webpack_modules__查詢模塊847并執(zhí)行

          // 傳入模塊847的導(dǎo)出對(duì)象,以及require接口__webpack_modules__[moduleId](module, module.exports, __webpack_require__)

          (5)返回模塊847的導(dǎo)出對(duì)象

          return module.exports

          圖解如下:


          橘黃色背景的元素代表數(shù)據(jù)

          綠色背景的元素代表函數(shù)

          總結(jié)

          通過模塊化的管理方式

          每個(gè)模塊都通過函數(shù)封裝在自己的局部環(huán)境中。 模塊與模塊之間通過require 接口進(jìn)行通信。且不用通過暴露在全局環(huán)境。

          每個(gè)模塊都明確通過require接口傳入依賴的模塊,所以模塊與模塊之間的依賴關(guān)系也是非常明了的。如圖a -> b -> c -> d


          模塊第1次被引用時(shí),調(diào)用require接口會(huì)像cache中添加導(dǎo)出對(duì)象。并返回添加的導(dǎo)出對(duì)象。

          模塊被第2+次引用時(shí),調(diào)用require接口查詢cache對(duì)象時(shí),返回cache中對(duì)應(yīng)的導(dǎo)出對(duì)象。


          本文完~


          瀏覽 76
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  狠狠草狠狠 | 久久精品国产人伦 | 小视频+福利 | 免费观看高清无码 | 色色影音|