CommonJs模塊化實現原理ES Module模塊化原理

CommonJs模塊化實現原理

首先看一個案例
初始化項目

npm init
npm i webpack -D

目錄結構如下

在這里插入圖片描述
webpack.config.js

const path = require("path");
module.exports = {mode: "development",entry: "./src/index.js",output: {path: path.resolve(__dirname, "dist"),filename: "[name].js",},devtool: "source-map"
};

src/index.js

const b = require("./b");
const a = require("./a");
console.log(a, b)

src/a.js

let a = "這是a"
module.exports = a;

src/b.js

let b = "這是b"
module.exports = b;

build.js

const { webpack } = require("webpack");
const webpackOptions = require("./webpack.config.js");const compiler = webpack(webpackOptions);compiler.run((err, stats) => {console.log(err)
});

進行node ./build.js后查看dist文件下

(() => { var __webpack_modules__ = ({"./src/a.js": ((module) => {let a = "這是a"module.exports = a;}),"./src/b.js":((module) => {let b = '這是b'module.exports = b;})});// The module cachevar __webpack_module_cache__ = {};// The require functionfunction __webpack_require__(moduleId) {// Check if module is in cachevar cachedModule = __webpack_module_cache__[moduleId];if (cachedModule !== undefined) {return cachedModule.exports;}// Create a new module (and put it into the cache)var module = __webpack_module_cache__[moduleId] = {// no module.id needed// no module.loaded neededexports: {}};// Execute the module function__webpack_modules__[moduleId](module, module.exports, __webpack_require__);// Return the exports of the modulereturn module.exports;}var __webpack_exports__ = {};(() => {const b = __webpack_require__("./src/b.js");const a = __webpack_require__("./src/a.js");console.log(a, b);})();})()
;
//# sourceMappingURL=main.js.map

分析一下打包產物

首先看下 webpack_modules,我們在src/index.js中引入了a.js、b.js, webpack會把’src/a.js’、‘src/b.js’作為modules的key值,該模塊內容作為modules的value值;

 var __webpack_modules__ = ({"./src/a.js": ((module) => {let a = "這是a"module.exports = a;}),"./src/b.js":((module) => {let b = '這是b'module.exports = b;})});

定義 __webpack_require__函數

	var __webpack_module_cache__ = {};function __webpack_require__(moduleId) {// 判斷一下緩存中有沒有當前modulevar cachedModule = __webpack_module_cache__[moduleId];if (cachedModule !== undefined) {// 緩存中有的話走緩存,返回cachedModule.exportsreturn cachedModule.exports;}// 緩存中沒有就重新創建一個moudle,設置export對象,并放入緩存var module = __webpack_module_cache__[moduleId] = {exports: {}};// 執行模塊代碼, 傳入當前module,根據需要傳入module.exports, __webpack_require__,module.exports會在模塊中賦值__webpack_modules__[moduleId](module, module.exports, __webpack_require__);// 返回module.exportsreturn module.exports;}

執行入口函數,為防止命名污染,封裝成立即執行函數。

 (() => {const b = __webpack_require__("./src/b.js");const a = __webpack_require__("./src/a.js");console.log(a, b);})();

ES Module模塊化原理

src/index.js

import a from './a'
import {b} from './b'
console.log(a, b);

src/a.js

const a = "這是a"
export default a

src/b.js

export const b = '這是b'

node ./build.js 之后main.js如下:

 (() => { "use strict";var __webpack_modules__ = ({"./src/a.js":((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {__webpack_require__.r(__webpack_exports__);__webpack_require__.d(__webpack_exports__, {"default": () => (__WEBPACK_DEFAULT_EXPORT__)});const a = "這是a"const __WEBPACK_DEFAULT_EXPORT__ = (a);}),"./src/b.js":((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {__webpack_require__.r(__webpack_exports__);__webpack_require__.d(__webpack_exports__, {b: () => (b)});const b = '這是b'})});var __webpack_module_cache__ = {};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;}(() => {__webpack_require__.d = (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_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))})();(() => {__webpack_require__.r = (exports) => {if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });}Object.defineProperty(exports, '__esModule', { value: true });};})();var __webpack_exports__ = {};(() => {__webpack_require__.r(__webpack_exports__);var _a__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/a.js");var _b__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/b.js");console.log(_a__WEBPACK_IMPORTED_MODULE_0__["default"], _b__WEBPACK_IMPORTED_MODULE_1__.b);})();})()
;
//# sourceMappingURL=main.js.map

如果是通過export default 方式導出的,那就在 exports 對象加一個 default 屬性

var __webpack_modules__ = ({"./src/a.js":((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {// 在 ESM 模式下聲明 ESM 模塊標識__webpack_require__.r(__webpack_exports__);// 將模塊導出的內容附加的模塊對象上,如果是通過export default導出,給exports的對象加default屬性__webpack_require__.d(__webpack_exports__, {"default": () => (__WEBPACK_DEFAULT_EXPORT__)});const a = "這是a"const __WEBPACK_DEFAULT_EXPORT__ = (a);}),"./src/b.js":((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {__webpack_require__.r(__webpack_exports__);__webpack_require__.d(__webpack_exports__, {b: () => (b)});const b = '這是b'})});

通過__webpack_require__.r把模塊標識為 ES Module
了解Symbol.toStringTag

(() => {__webpack_require__.r = (exports) => {if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });}Object.defineProperty(exports, '__esModule', { value: true });};})();

通過__webpack_require__.d對exports做代理

(() => {__webpack_require__.d = (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_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))})();

ES Module加載CommonJS實現原理
src/index.js

import b from './b'
console.log(b);

src/b.js

let b = '這是b'
module.exports = b;

node ./build.js之后

 (() => { var __webpack_modules__ = ({"./src/b.js": ((module) => {let b = '這是b'module.exports = b;})});var __webpack_module_cache__ = {};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;}(() => {__webpack_require__.n = (module) => {var getter = module && module.__esModule ?() => (module['default']) :() => (module);__webpack_require__.d(getter, { a: getter });return getter;};})();(() => {__webpack_require__.d = (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_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))})();(() => {__webpack_require__.r = (exports) => {if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });}Object.defineProperty(exports, '__esModule', { value: true });};})();var __webpack_exports__ = {};(() => {"use strict";__webpack_require__.r(__webpack_exports__);var _b__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/b.js");var _b__WEBPACK_IMPORTED_MODULE_0___default = __webpack_require__.n(_b__WEBPACK_IMPORTED_MODULE_0__);console.log((_b__WEBPACK_IMPORTED_MODULE_0___default()));})();})()
;
//# sourceMappingURL=main.js.map

由此可以看出加了這一個步驟:
通過__webpack_require__.n判斷模塊是否是esModule返回module

	(() => {__webpack_require__.n = (module) => {var getter = module && module.__esModule ?() => (module['default']) :() => (module);__webpack_require__.d(getter, { a: getter });return getter;};})();

CommonJS加載ES Module的實現原理

src/index.js

const b = require('./b.js')
console.log(b);

src/b.js

let b = '這是b'
export default b;

node ./build.js之后

 (() => {var __webpack_modules__ = ({"./src/b.js": ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {"use strict";__webpack_require__.r(__webpack_exports__);__webpack_require__.d(__webpack_exports__, {"default": () => (__WEBPACK_DEFAULT_EXPORT__)});let b = '這是b'const __WEBPACK_DEFAULT_EXPORT__ = (b);})});var __webpack_module_cache__ = {};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;}(() => {__webpack_require__.d = (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_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))})();(() => {__webpack_require__.r = (exports) => {if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });}Object.defineProperty(exports, '__esModule', { value: true });};})();var __webpack_exports__ = {};(() => {const b = __webpack_require__(/*! ./b.js */ "./src/b.js")console.log(b);})();})()
;
//# sourceMappingURL=main.js.map

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/215940.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/215940.shtml
英文地址,請注明出處:http://en.pswp.cn/news/215940.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

硬件開發筆記(十六):RK3568底板電路mipi攝像頭接口原理圖分析、mipi攝像頭詳解

若該文為原創文章,轉載請注明原文出處 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/134922307 紅胖子網絡科技博文大全:開發技術集合(包含Qt實用技術、樹莓派、三維、OpenCV、OpenGL、ffmpeg、OSG、單片機、軟硬…

Redis緩存主要異常及解決方案

1 導讀 Redis 是當前最流行的 NoSQL數據庫。Redis主要用來做緩存使用,在提高數據查詢效率、保護數據庫等方面起到了關鍵性的作用,很大程度上提高系統的性能。當然在使用過程中,也會出現一些異常情景,導致Redis失去緩存作用。 2 異常類型 異常主要有 緩存雪崩 緩存穿透 緩…

【sqli靶場】第二關和第三關通關思路

目錄 前言 一、sqli靶場第二關 1.1 判斷注入類型 1.2 判斷數據表中的列數 1.3 使用union聯合查詢 1.4 使用group_concat()函數 1.5 爆出users表中的列名 1.6 爆出users表中的數據 二、sqli靶場第三關 2.1 判斷注入類型 2.2 觀察報錯 2.3 判斷數據表中的列數 2.4 使用union聯合…

Emutouch學習筆記

1 項目依賴 DeviceFarmer/minitouch 1.1 確認submodule引用的 commit ID git submodule status1.2 更新子模塊到最新版本 git submodule init && git submodule update --remote

Android:監聽開機廣播自己喚醒

要通過代碼獲取安卓系統的開機廣播消息,并在收到消息后拉起當前apk,您可以使用以下步驟: 創建一個廣播接收器(Broadcast Receiver)來接收開機廣播消息。在接收到開機廣播消息時,您可以在接收器中編寫代碼來…

什么是 web 組態?web 組態與傳統組態的區別是什么?

組態軟件是一種用于控制和監控各種設備的軟件,也是指在自動控制系統監控層一級的軟件平臺和開發環境。這類軟件實際上也是一種通過靈活的組態方式,為用戶提供快速構建工業自動控制系統監控功能的、通用層次的軟件工具。通常用于工業控制,自動…

Spring Boot整合 Spring Security

Spring Boot整合 1、RBAC 權限模型 RBAC模型(Role-Based Access Control:基于角色的訪問控制) 在RBAC模型里面,有3個基礎組成部分,分別是:用戶、角色和權限,它們之間的關系如下圖所示 SELECT…

02.類模板

2、類模板 2.1 類模板語法 建立一個通用類&#xff0c;類中的成員、數據類型可以不具體制定&#xff0c;用一個虛擬的類型來代表。 template<typename T> // 類template&#xff1a;聲明創建模板typename&#xff1a;表名其后面的符號是一種數據類型&#xff0c;可以用 …

【算法】算法題-20231211

這里寫目錄標題 一、387. 字符串中的第一個唯一字符二、1189. “氣球” 的最大數量三、1221. 分割平衡字符串 一、387. 字符串中的第一個唯一字符 簡單 給定一個字符串 s &#xff0c;找到 它的第一個不重復的字符&#xff0c;并返回它的索引 。如果不存在&#xff0c;則返回…

算法通關村第十五關 | 青銅 | 用4KB內存尋找重復元素

處理海量數據的思路 1.使用位存儲&#xff1a;占用的空間是存整數的 1/8 。 2.分塊&#xff1a;也叫外部排序&#xff0c;將大文件劃分為若干小塊&#xff0c;先處理小塊再逐步得到想要的結果&#xff0c;需要至少遍歷兩次全部序列&#xff0c;是用時間換空間的方法。 3.堆&…

Mockjs 增、刪、改、查(分頁、多條件查詢)

查&#xff08;分頁、多條件查詢&#xff09;&#xff1a; 關鍵代碼&#xff1a; Mock.mock(/vue-table-list/tableLinkage/list, post, (option) > {// console.log("&#x1f680; ~ file: tableLinkage.js:66 ~ Mock.mock ~ option:", option)const params J…

MFC畫折線圖,基于x64系統

由于項目的需要&#xff0c;需要畫一個折線圖。 傳統的Teechart、MSChart、HighSpeedChart一般是只能配置在x86系統下&#xff0c;等到使用x64系統下運行就是會報出不知名的錯誤&#xff0c;這個地方讓人很苦惱。 我在進行配置的過程之中&#xff0c;使用Teechart將x86配置好…

基于Java SSM框架實現班級同學錄、聚會報名網站系統項目【項目源碼+論文說明】

基于java的SSM框架實現班級同學錄聚會報名網站系統演示 摘要 21世紀的今天&#xff0c;隨著社會的不斷發展與進步&#xff0c;人們對于信息科學化的認識&#xff0c;已由低層次向高層次發展&#xff0c;由原來的感性認識向理性認識提高&#xff0c;管理工作的重要性已逐漸被人…

程序員考公筆記之邏輯判斷(圖形推理)

文章目錄 寫在前面1、邏輯判斷1.1、圖形推理1.1.1、位置類1.1.2、樣式類1.1.3、數量類1.1.4、屬性類1.1.5、六面體 寫在前面 1、邏輯判斷 1.1、圖形推理 觀察&#xff1a;先宏觀&#xff0c;再微觀 圖形推理的命題形式&#xff1a; 一組式 觀察路徑&#xff1a;順序看(考最…

解決方案- 材料吸波、屏蔽性能測試系統 (10MHz~500GHz)

材料吸波、屏蔽性能測試系統 &#xff08;10MHz~500GHz&#xff09; 材料電磁參數綜合測試解決方案 材料吸波、屏蔽性能測試系統測試頻率范圍可達10MHz&#xff5e;500GHz&#xff0c;可實現材料反射率、屏蔽性能特性參數測試。系統由矢量網絡分析儀、測試夾具、系統軟件等組…

申論筆記(思路技巧)

文章目錄&#xff1a; 一&#xff1a;福利 二&#xff1a;常見題型 1.歸納概括題 2.提出對策/措施/建議題 2.1 找到對策的來源 2.2 提煉對策 2.3 明確是否需要先概括問題 2.4 對策表述三部曲 3.綜合分析題 3.1 綜合分析最大的難點 3.2 分析問題的技巧 4.應用文/公文…

力扣每日一題day34[110. 平衡二叉樹]

給定一個二叉樹&#xff0c;判斷它是否是高度平衡的二叉樹。 本題中&#xff0c;一棵高度平衡二叉樹定義為&#xff1a; 一個二叉樹每個節點 的左右兩個子樹的高度差的絕對值不超過 1 。 示例 1&#xff1a; 輸入&#xff1a;root [3,9,20,null,null,15,7] 輸出&#xff1a;t…

wappalyzer基于插件的網站開發技術解析工具

一、wappalyzer 解釋&#xff1a;這是一款強大的工具&#xff0c;其主要能提供一種快速、可靠地檢測網站所使用技術棧的方法&#xff0c;也就說說&#xff0c;服務器發來的信息都會被它剖析&#xff0c;然后分析出前端的技術棧&#xff0c;有時后端所使用的技術棧如果網頁特征…

[ 藍橋杯Web真題 ]-冬奧大抽獎

目錄 介紹 準備 目標 規定 思路 知識補充 解法參考 介紹 藍橋云課慶冬奧需要舉行一次抽獎活動&#xff0c;我們一起做一個頁面提供給云課冬奧抽獎活動使用。 準備 開始答題前&#xff0c;需要先打開本題的項目代碼文件夾&#xff0c;目錄結構如下&#xff1a; ├──…

甲醛處理企業網站效果如何

甲醛往往是新裝房間主所擔心的問題&#xff0c;而甲醛處理公司則可以處理甲醛問題&#xff0c;市場需求也比較高&#xff0c;雖然具備同城服務屬性&#xff0c;但外地或連鎖經營也非常適合&#xff0c;而品牌們也遇到一些痛點&#xff1a; 1、品牌宣傳拓客難 甲醛處理公司也需…