webpack模块化实现原理

5/13/2021 Webpack

# 文章目录

# 一、准备

目录结构:

├── common_index.js
├── es_index.js
├── index.js
└── js
    ├── format.js
    └── math.js
1
2
3
4
5
6

如果有需要源码的,评论或者私信一下,我也不确定有没有人需要,就懒得放了。

# 二、CommonJS 实现原理

去掉所有注释,和一些 外层的立即执行函数后。

// 定义了一个对象
// 模块的路径(key): 函数(value)
var __webpack_modules__ = {
  "./src/js/formate.js": function(module) {
    const dateFormat = (date) => {
      console.log("2020-1-1");
    };
    const priceFormat = (price) => {
      console.log("100.00");
    };
    // 5.
    // 将我们要导出的其他变量,放入到module对象中的exports对象里
    module.exports = {
      dateFormat,
      priceFormat,
    };
  },
};

// 定义了一个对象,作为加载模块的缓存
var __webpack_module_cache__ = {};

// 函数,当我们加载一个模块时,都会通过这个函数来加载
function __webpack_require__(moduleId) {
  var cachedModule = __webpack_module_cache__[moduleId];
  // 2. 判断缓存中是否存在
  if (cachedModule !== undefined) {
    return cachedModule.exports;
  }

  // 3. 给 module对象 和  __webpack_module_cache__[moduleId]  赋值了同一个对象,
  var module = (__webpack_module_cache__[moduleId] = {
    exports: {},
  });

  //  4. 加载执行模块
  __webpack_modules__[moduleId](module, module.exports, __webpack_require__);

  // 6. 导出 module.exports
  return module.exports;
}

//
var __webpack_exports__ = {};

// 立即执行函数的变种写法,具体开始执行代码逻辑
!(function() {
  // 1. 加载模块
  const { dateFormat, priceFormat } = __webpack_require__(
    "./src/js/formate.js"
  );

  // 7. 导出
  dateFormat("1");
  priceFormat("1");
})();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

# 三、ESModule 实现原理

// 1. 定义了一个对象,对象里边放的是我们的模块映射
var __webpack_modules__ = {
  "./src/js/math.js": function(
    __unused_webpack_module,
    __webpack_exports__,
    __webpack_require__
  ) {
    __webpack_require__.r(__webpack_exports__);
    __webpack_require__.d(__webpack_exports__, {
      sum: function() {
        return sum;
      },
      mul: function() {
        return mul;
      },
    });
    const sum = (num1, num2) => {
      return num1 + num2;
    };
    const mul = (num1, num2) => {
      return num1 * num2;
    };
  },
};

// 2.缓存
var __webpack_module_cache__ = {};

// 3. require 函数的实现(加载模块)
function __webpack_require__(moduleId) {
  var cachedModule = __webpack_module_cache__[moduleId];
  if (cachedModule !== undefined) {
    return cachedModule.exports;
  }
  var module = (__webpack_module_cache__[moduleId] = {
    exports: {},
  });

  __webpack_modules__[moduleId](module, module.exports, __webpack_require__);

  return module.exports;
}

!(function() {
  // 给这个函数对象添加了一个属性, d => funciton
  __webpack_require__.d = function(exports, definition) {
    for (var key in definition) {
      if (
        __webpack_require__.o(definition, key) &&
        !__webpack_require__.o(exports, key)
      ) {
        // 做了一个代理,__webpack_modules__  上的方法 代理到 _js_math__WEBPACK_IMPORTED_MODULE_0__
        Object.defineProperty(exports, key, {
          enumerable: true,
          get: definition[key],
        });
      }
    }
  };
})();

!(function() {
  // 给这个函数对象添加了一个属性, o => funciton
  __webpack_require__.o = function(obj, prop) {
    // 判断 obj 对象原生属性上是否具有 prop 属性
    return Object.prototype.hasOwnProperty.call(obj, prop);
  };
})();

!(function() {
  // 给这个函数对象添加了一个属性, r => funciton
  __webpack_require__.r = function(exports) {
    if (typeof Symbol !== "undefined" && Symbol.toStringTag) {
      // 增加了一个属性 值是 Module
      Object.defineProperty(exports, Symbol.toStringTag, {
        value: "Module",
      });
    }
    // 增加了一个属性 值是 __esModule
    Object.defineProperty(exports, "__esModule", {
      value: true,
    });
  };
})();

var __webpack_exports__ = {};

!(function() {
  __webpack_require__.r(__webpack_exports__);
  var _js_math__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(
    "./src/js/math.js"
  );

  console.log(_js_math__WEBPACK_IMPORTED_MODULE_0__.mul(20, 30));
  console.log(_js_math__WEBPACK_IMPORTED_MODULE_0__.sum(20, 30));
})();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

# 四、CommonJS 和 ESModule 相互导入原理

var __webpack_modules__ = {
  "./src/index.js": function(
    __unused_webpack_module,
    __webpack_exports__,
    __webpack_require__
  ) {
    "use strict";
    __webpack_require__.r(__webpack_exports__);
    var _js_format__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(
      "./src/js/format.js"
    );
    var _js_format__WEBPACK_IMPORTED_MODULE_0___default = __webpack_require__.n(
      _js_format__WEBPACK_IMPORTED_MODULE_0__
    );

    // es module导出内容, CommonJS导入内容
    const math = __webpack_require__("./src/js/math.js");

    // CommonJS导出内容, es module导入内容
    console.log(math.sum(20, 30));
    console.log(math.mul(20, 30));
    console.log(
      _js_format__WEBPACK_IMPORTED_MODULE_0___default().dateFormat("aaa")
    );
    console.log(
      _js_format__WEBPACK_IMPORTED_MODULE_0___default().priceFormat("bbb")
    );
  },
  "./src/js/format.js": function(module) {
    const dateFormat = (date) => {
      return "2020-12-12";
    };
    const priceFormat = (price) => {
      return "100.00";
    };
    module.exports = {
      dateFormat,
      priceFormat,
    };
  },

  "./src/js/math.js": function(
    __unused_webpack_module,
    __webpack_exports__,
    __webpack_require__
  ) {
    __webpack_require__.r(__webpack_exports__);
    __webpack_require__.d(__webpack_exports__, {
      sum: function() {
        return sum;
      },
      mul: function() {
        return mul;
      },
    });
    const sum = (num1, num2) => {
      return num1 + num2;
    };

    const mul = (num1, num2) => {
      return num1 * num2;
    };
  },
};

var __webpack_module_cache__ = {};

// The require function
function __webpack_require__(moduleId) {
  // Check if module is in cache
  if (__webpack_module_cache__[moduleId]) {
    return __webpack_module_cache__[moduleId].exports;
  }
  // Create a new module (and put it into the cache)
  var module = (__webpack_module_cache__[moduleId] = {
    // no module.id needed
    // no module.loaded needed
    exports: {},
  });

  // Execute the module function
  __webpack_modules__[moduleId](module, module.exports, __webpack_require__);

  // Return the exports of the module
  return module.exports;
}

!(function() {
  // getDefaultExport function for compatibility with non-harmony modules
  __webpack_require__.n = function(module) {
    var getter =
      module && module.__esModule
        ? function() {
            return module["default"];
          }
        : function() {
            return module;
          };
    __webpack_require__.d(getter, { a: getter });
    return getter;
  };
})();

/* webpack/runtime/define property getters */
!(function() {
  // define getter functions for harmony exports
  __webpack_require__.d = function(exports, definition) {
    for (var key in definition) {
      if (
        __webpack_require__.o(definition, key) &&
        !__webpack_require__.o(exports, key)
      ) {
        Object.defineProperty(exports, key, {
          enumerable: true,
          get: definition[key],
        });
      }
    }
  };
})();

/* webpack/runtime/hasOwnProperty shorthand */
!(function() {
  __webpack_require__.o = function(obj, prop) {
    return Object.prototype.hasOwnProperty.call(obj, prop);
  };
})();

/* webpack/runtime/make namespace object */
!(function() {
  // define __esModule on exports
  __webpack_require__.r = function(exports) {
    if (typeof Symbol !== "undefined" && Symbol.toStringTag) {
      Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
    }
    Object.defineProperty(exports, "__esModule", { value: true });
  };
})();

__webpack_require__("./src/index.js");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
最后更新于: 2021年9月15日星期三晚上10点10分
Dawn
DDRKirby(ISQ)