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 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))
 })();

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

VBA信息获取与处理:在EXCEL中随机函数的利用

《VBA信息获取与处理》教程(版权10178984)是我推出第六套教程,目前已经是第一版修订了。这套教程定位于最高级,是学完初级,中级后的教程。这部教程给大家讲解的内容有:跨应用程序信息获得、随机信息的利用、电子邮件的发送、VBA互…

助力工业生产质检,基于轻量级yolov5-seg开发构建工业场景下滚珠丝杠传动表面缺陷分割检测系统

AI赋能工业生产是一个强有力的方式,在我们之前的系列博文中也有很多相应的开发实践,感兴趣的胡都可以自行移步阅读,本文的核心思想就是想要基于轻量级的实例分割模型来开发构建工业场景下的滚珠丝杠传动表面缺陷分割检测系统,首先…

Openwrt源码下载出现“The remote end hung up unexpected”

最近项目原因需要下载openwrt21.02版本源码,花费了很多时间,找到正确方法后,发现可以节省很多时间,记录下过程,方便自己,可能方便他人。 一.问题阐述 openwrt21.02下载链接如下: git clone -…

Springboot入门篇

一、概述 Spring是一个开源框架,2003 年兴起的一个轻量级的Java 开发框架,作者Rod Johnson 。Spring是为了解决企业级应用开发的复杂性而创建的,简化开发。 1.1对比 对比一下 Spring 程序和 SpringBoot 程序。如下图 坐标 Spring 程序中的…

【华为数据之道学习笔记】3-11元数据管理

1. 产生元数据 (1)明确业务元数据、技术元数据和操作元数据之间的关系,定义华为公司元数据模型。 (2)针对找数据及获取数据难的痛点,明确业务元数据、技术元数据、操作元数据的设计原则。 1)业务…

Pytorch-LSTM轴承故障一维信号分类(一)

目录 前言 1 数据集制作与加载 1.1 导入数据 第一步,导入十分类数据 第二步,读取MAT文件驱动端数据 第三步,制作数据集 第四步,制作训练集和标签 1.2 数据加载,训练数据、测试数据分组,数据分batch…

C++之STL算法(1)

STL容器算法主要由、、组成;   algorithm主要有遍历、比较、交换、查找、拷贝、修改等; 1.遍历容器for_each for_each()函数用于完成容器遍历,函数参数如下: for_each(_InIt _First, _InIt _Last, _Fn _Func) 形参&#xff1a…

mybatis多表映射-延迟加载,延迟加载的前提条件是:分步查询

1、建库建表 create database mybatis-example; use mybatis-example; create table t_book (bid varchar(20) primary key,bname varchar(20),stuid varchar(20) ); insert into t_book values(b001,Java,s001); insert into t_book values(b002,Python,s002); insert into …

基于 librosa和soundfile对音频进行重采样 (VITS 必备)

基于 librosa和soundfile对音频进行重采样 一、前言 在玩bert-vits2的时候有对音频进行重采样的需求,故写了一下批量对音频进行重采样的脚本。 优化点: 根据机器自适应线程数为最多,保证充分利用机器资源,提高速度>30%。支持…

UE引擎 LandscapeGrass 实现机制分析(UE5.2)

前言 随着电脑和手机硬件性能越来越高,游戏越来越追求大世界,而大世界非常核心的一环是植被,目前UE5引擎提供给植被生成的主流两种方式为 手刷植被和LandscapeGrass(WeightMap程序化植被)。当然UE5.3推出新一代PCGFramework 节点程序化生成框…

Android 顶部对齐宽度撑满高度等比例缩放及限制最大最小高度

一 示例 二 代码 <?xml version"1.0" encoding"utf-8"?> <FrameLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent&qu…

点评项目——秒杀优化

2023.12.11 上一张的秒杀券下单还可以进行优化&#xff0c;先来回顾一下下单流程&#xff1a; 可以看出流程设计多次查询和操作数据库的操作&#xff0c;并且执行顺序是一个线程串行执行&#xff0c;执行性能是比较低的。 优化方案&#xff1a;我们将判断秒杀库存和校验一人一单…

蓝桥杯周赛 第 1 场 强者挑战赛 6. 小球碰撞【算法赛】(思维题/最长上升子序列LIS)

题目 https://www.lanqiao.cn/problems/9494/learning/?contest_id153 思路来源 Aging代码 题解 二分时间t&#xff0c;第i个小球对应一个起点pi、终点pit*vi的区间&#xff0c;问题转化为&#xff0c; 选最多的区间&#xff0c;使得不存在区间包含&#xff08;即li<l…

第二百零一回 介绍一个三方包open_settings

文章目录 1. 概念介绍2 使用方法3 代码与效果3.1 示例代码3.2 运行效果 4. 经验分享 我们在上一章回中介绍了Form Widget相关的内容&#xff0c;本章回中将介绍Form系列组件的验证与提交功能.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在这里说的的验…

【电路笔记】-电位器

电位器 文章目录 电位器1、概述2、电位器类型2.1 旋转电位器2.2 滑块电位器2.3 预设和微调电位器2.4 变阻器 3、电位器示例14、电位器作为分压器5、电位器示例26、变阻器6、滑块变阻器7、线性或对数电位器8、总结 当连接的轴物理旋转时&#xff0c;电位计和变阻器的电阻值会发生…

23种设计模式之装饰者模式(被装饰者,接口层,装饰抽象层,具体装饰者)

23种设计模式之装饰者模式 文章目录 23种设计模式之装饰者模式设计思想装饰者模式的优点装饰者模式的缺点装饰者模式的优化方法UML 解析预设场景 代码释义总结 设计思想 原文:装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0…

【EMNLP 2023】面向垂直领域的知识预训练语言模型

近日&#xff0c;阿里云人工智能平台PAI与华东师范大学数据科学与工程学院合作在自然语言处理顶级会议EMNLP2023上发表基于双曲空间和对比学习的垂直领域预训练语言模型。通过比较垂直领域和开放领域知识图谱数据结构的不同特性&#xff0c;发现在垂直领域的图谱结构具有全局稀…

做数据分析为何要学统计学(3)——何为置信区间?它有什么作用?

置信区间是统计学中的一个重要工具&#xff0c;用以使用样本参数()来估计总体均值在某置信水平下的范围。通俗一点讲&#xff0c;如果置信度为95%&#xff08;等价于显著水平a0.05&#xff09;&#xff0c;置信区间为[a,b]&#xff0c;这就意味着总体均值落入该区间的概率为95%…

虹科Pico汽车示波器 | 汽车免拆检修 | 2019款别克GL8豪华商务车前照灯水平调节故障

一、故障现象 一辆2019款别克GL8豪华商务车&#xff0c;搭载LTG发动机&#xff0c;累计行驶里程约为10.7万km。车主反映&#xff0c;车辆行驶过程中组合仪表提示前照灯水平调节故障。 二、故障诊断 接车后试车&#xff0c;起动发动机&#xff0c;组合仪表上提示“前照灯水平调节…

Spring Boot监听redis过期的key

Redis支持过期监听&#xff0c;可以实现监听过期数据&#xff0c;实现过程如下 1、pom依赖 <!-- Redis--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></depend…