♣ 模組化原理和source-map
阿新 • • 發佈:2022-02-13
Webpack的模組化
Webpack打包的程式碼,允許我們使用各種各樣的模組化,但是最常用的是CommonJS、ES Module。那麼它是如何幫助我們實現了程式碼中支援模組化呢?
我們來研究一下它的原理,包括如下原理:
- CommonJS模組化實現原理;
- ES Module實現原理;
- CommonJS載入ES Module的原理;
- ES Module載入CommonJS的原理;
CommonJS的實現原理
檢視程式碼
// 定義了一個物件 // 模組的路徑(key): 函式(value) var __webpack_modules__ = { "./src/js/format.js": (function (module) { const dateFormat = (date) => { return "2020-12-12"; } const priceFormat = (price) => { return "100.00"; } // 將我們要匯出的變數, 放入到module物件中的exports物件 module.exports = { dateFormat, priceFormat } }) } // 定義一個物件, 作為載入模組的快取 var __webpack_module_cache__ = {}; // 是一個函式, 當我們載入一個模組時, 都會通過這個函式來載入 function __webpack_require__(moduleId) { // 1.判斷快取中是否已經載入過 if (__webpack_module_cache__[moduleId]) { return __webpack_module_cache__[moduleId].exports; } // 2.給module變數和__webpack_module_cache__[moduleId]賦值了同一個物件 var module = __webpack_module_cache__[moduleId] = { exports: {} }; // 3.載入執行模組 __webpack_modules__[moduleId](module, module.exports, __webpack_require__); // 4.匯出module.exports {dateFormat: function, priceForamt: function} return module.exports; } // 具體開始執行程式碼邏輯 !function () { // 1.載入./src/js/format.js const { dateFormat, priceFormat } = __webpack_require__("./src/js/format.js"); console.log(dateFormat("abc")); console.log(priceFormat("abc")); }();
ESModule的實現原理
檢視程式碼
// 1.定義了一個物件, 物件裡面放的是我們的模組對映 var __webpack_modules__ = { "./src/es_index.js": (function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { // 呼叫r的目的是記錄時一個__esModule -> true __webpack_require__.r(__webpack_exports__); // _js_math__WEBPACK_IMPORTED_MODULE_0__ == 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)); }), "./src/js/math.js": (function (__unused_webpack_module, __webpack_exports__, __webpack_require__) { __webpack_require__.r(__webpack_exports__); // 呼叫了d函式: 給exports設定了一個代理definition // 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) { if (__webpack_module_cache__[moduleId]) { return __webpack_module_cache__[moduleId].exports; } var module = __webpack_module_cache__[moduleId] = { exports: {} }; __webpack_modules__[moduleId](module, module.exports, __webpack_require__); return module.exports; } !function () { // __webpack_require__這個函式物件添加了一個屬性: d -> 值function __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] }); } } }; }(); !function () { // __webpack_require__這個函式物件添加了一個屬性: o -> 值function __webpack_require__.o = function (obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } }(); !function () { // __webpack_require__這個函式物件添加了一個屬性: r -> 值function __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/es_index.js");
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");