CommonJs模块化实现原理ES Module模块化原理

news2024/12/26 10:55:39

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 cache
 	var __webpack_module_cache__ = {};
 	
 	// The require function
 	function __webpack_require__(moduleId) {
 		// Check if module is in cache
 		var 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 needed
 			exports: {}
 		};
 	
 		// Execute the module function
 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
 	
 		// Return the exports of the module
 		return 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) {
		// 判断一下缓存中有没有当前module
		var cachedModule = __webpack_module_cache__[moduleId];
		if (cachedModule !== undefined) {
			// 缓存中有的话走缓存,返回cachedModule.exports
			return 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.exports
 		return 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))
 })();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1302131.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

项目经理和产品经理哪个更有发展前景?

如果是单看“钱途”的话,如果是在传统行业,可能差不多;如果是在IT行业的话,可能更需要项目经理;互联网行业的话,可能更需要产品经理。 项目经理跟产品经理两个证都挺受市场欢迎的,两个岗位职责…

关于粒子群算法的一些简单尝试

粒子群算法核心思想:(鸟 粒子) (1)许多的鸟站在不同的地方; (2)每一只鸟都有自己寻找食物的初始飞行方向、飞行速度; (3)这些鸟儿每隔一段时间…

高级网工在Linux服务器抓包,少不了这几条常用的tcpdump命令。

Linux 的命令太多,tcpdump 是一个非常强大的抓包命令。有时候想看线上发生的一些问题: nginx 有没有客户端连接过来…… 客户端连接过来的时候 Post 上来的数据对不对…… 我的 Redis 实例到底是哪些业务在使用…… tcpdump 作为网络分析神器就派上用场…

湖农大邀请赛shell_rce漏洞复现

湖农大邀请赛 shell_rce 复现 在 2023 年湖南农业大学邀请赛的线上初赛中&#xff0c;有一道 shell_rce 题&#xff0c;本文将复现该题。 题目内容&#xff0c;打开即是代码&#xff1a; <?phpclass shell{public $exp;public function __destruct(){$str preg_replace…

2、快速搞定Kafka术语

快速搞定Kafka术语 Kafka 服务端3层消息架构 Kafka 客户端Broker 如何持久化数据小结 Kafka 服务端 3层消息架构 第 1 层是主题层&#xff0c;每个主题可以配置 M 个分区&#xff0c;而每个分区又可以配置 N 个副本。第 2 层是分区层&#xff0c;每个分区的 N 个副本中只能有…

Java集合进阶

目录 集合体系结构 Collection集合 List集合 ArrayList集合 LinkedList集合 集合体系结构 注意:有序:存进去的数组和取出来时一样 而不是大小的那种有序 Collection集合 单列集合顶层接口Collection import java.util.ArrayList; import java.util.Collection;public cl…

模块化机房在大数据时代的角色:高效、可扩展的数据存储和处理平台

随着大数据时代的到来&#xff0c;数据已经成为企业竞争的核心资源。然而&#xff0c;传统的数据中心已经无法满足现代业务的需求&#xff0c;尤其是在数据存储和处理方面。模块化机房作为一种新型的数据中心建设模式&#xff0c;具有高效、可扩展等优势&#xff0c;逐渐成为大…

SQL命令---删除字段

介绍 使用sql语句删除表字段。 命令 alter table 表名 drop 字段名;例子 删除a表中的name字段。 alter table a drop name;下面是执行删除后的表结构&#xff1a;

《opencv实用探索·十六》opencv直方图计算calcHist函数解析

直方图理解&#xff1a; &#xff08;对于8位灰度图像亮度/灰度为(0-255)&#xff0c;12位灰度图像亮度/灰度为(0-4095)&#xff09; 以8位图像为例&#xff0c;亮度分为0到255共256个数值&#xff0c;数值越大&#xff0c;代表的亮度越高。其中0代表纯黑色的最暗区域&#xff…

XCube——用于超高分辨率 3D 形状和场景的生成模型!

他们的方法在稀疏体素网格的层次结构上训练潜在扩散模型的层次结构。他们在稀疏结构 VAE 的潜在空间上进行扩散&#xff0c;它为层次结构的每个级别学习紧凑的潜在表示。 XCube 是稀疏体素层次上的分层潜在扩散模型&#xff0c;即从粗到细的 3D 稀疏体素网格序列&#xff0c;使…

OpenWRT搭建本地web站点并结合内网穿透实现公网远程访问

文章目录 前言1. 检查uhttpd安装2. 部署web站点3. 安装cpolar内网穿透4. 配置远程访问地址5. 配置固定远程地址 前言 uhttpd 是 OpenWrt/LuCI 开发者从零开始编写的 Web 服务器&#xff0c;目的是成为优秀稳定的、适合嵌入式设备的轻量级任务的 HTTP 服务器&#xff0c;并且和…

【高数:3 无穷小与无穷大】

【高数&#xff1a;3 无穷小与无穷大】 1 无穷小与无穷大2 极限运算法则3 极限存在原则4 趋于无穷小的比较 参考书籍&#xff1a;毕文斌, 毛悦悦. Python漫游数学王国[M]. 北京&#xff1a;清华大学出版社&#xff0c;2022. 1 无穷小与无穷大 无穷大在sympy中用两个字母o表示无…

数据结构--二叉树

目录 1.二叉树链式结构的实现 1.1 前置说明 1.2 二叉树的遍历 1.2.1 前序、中序以及后序遍历 1.2.2 层序遍历及判断是否为完全二叉树 1.3 节点个数&#xff0c;叶子节点个数&#xff0c;第k层节点个数以及高度等 1.4 二叉树的创建和销毁 1.二叉树链式结构的实现 1.1 前置说…

使用人工智能优化常见业务流程

在现代商业环境中&#xff0c;人工智能(AI)正在改变企业的运营方式。将人工智能集成到业务流程中可以提高效率和准确性&#xff0c;从而节省大量时间和成本。 这使员工能够专注于更具战略性的任务。人工智能在商业中的应用范围从自动化日常任务到提供高级分析&#xff0c;以做…

Citespace、vosviewer、R语言的文献计量学可视化分析

文献计量学是指用数学和统计学的方法&#xff0c;定量地分析一切知识载体的交叉科学。它是集数学、统计学、文献学为一体&#xff0c;注重量化的综合性知识体系。特别是&#xff0c;信息可视化技术手段和方法的运用&#xff0c;可直观的展示主题的研究发展历程、研究现状、研究…

《杂文选刊》明年休刊之随笔

笔者今天偶然发现&#xff0c;网民对于近期登上社交网站热搜榜的一条新闻&#xff0c;既感兴趣又觉迷惑&#xff0c;因此关注度显得较高。 荣登社交网站热搜榜的这条新闻是&#xff1a;12月4日发出“休刊启事 ”&#xff0c;在宣布“《 杂文选刊》2024年1月1日起休刊”的同时&…

和鲸科技荣获第三届光合组织解决方案大赛集智赛道优秀奖

2023年11月28日&#xff0c;历经数月的“第三届光合组织解决方案大赛”落下帷幕&#xff0c;获奖榜单正式出炉。 本次大赛中&#xff0c;上海和今信息科技有限公司&#xff08;简称“和鲸科技”&#xff09;凭借多年深耕数据智能领域&#xff0c;提供关键基础设施催生人工智能…

解决HTTP 429错误的Scrapy中间件配置

引言 在进行网络数据抓取时&#xff0c;经常会遇到HTTP 429错误&#xff0c;表示请求速率已超出API限制。为避免封禁或限制访问&#xff0c;需要调整Scrapy的请求速率&#xff0c;以在不触发HTTP 429错误的情况下完成数据抓取。针对这一问题&#xff0c;可使用Scrapy的AutoThr…

Win11预览体验计划显示Your PC does not meet the minimum hardware requirements...的解决方案

某一天你心血来潮&#xff0c;打算参与Win11 预览体验计划&#xff0c;但体验计划页面却显示“Your PC does not meet the minimum hardware requirements for Windows11…”。 一种解决思路&#xff1a; 去以下网页下载Offline Insider Enroll软件&#xff0c;管理员权限运行…

安全开发:身份认证方案之 Google 身份验证器和基于时间的一次性密码 TOTP 算法

参考资料在文末注明&#xff0c;如本文有错漏欢迎评论区指出&#x1f44f; 目前很多应用都逐步采用了双因子认证或者说MFA认证方案&#xff0c;因此本文介绍一下背后的机制和TOTP算法原理。使用TOTP算法&#xff0c;只要满足两个条件&#xff1a;1&#xff09;基于相同的密钥&…