当前位置: 首页 > news >正文

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

相关文章:

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: p…...

实验4.1 静态路由的配置

实验4.1 静态路由的配置 一、任务描述二、任务分析三、具体要求四、实验拓扑五、任务实施1.设置交换机和路由器的基本配置。2.使用display ip interface brief命令查看接口配置信息。3.配置静态路由,实现全网互通。 六、任务验收七、任务小结 一、任务描述 某公司刚…...

Java网络编程-深入理解BIO、NIO

深入理解BIO与NIO BIO BIO 为 Blocked-IO(阻塞 IO),在 JDK1.4 之前建立网络连接时,只能使用 BIO 使用 BIO 时,服务端会对客户端的每个请求都建立一个线程进行处理,客户端向服务端发送请求后,…...

ShenYu网关注册中心之HTTP注册原理

文章目录 1、客户端注册流程1.1、读取配置1.1.1、用于注册的 HttpClientRegisterRepository1.1.2、用于扫描构建 元数据 和 URI 的 SpringMvcClientEventListener 1.2、扫描注解,注册元数据和URI1.2.1、构建URI并写入Disruptor1.2.2、构建元数据并写入Disruptor1.2.…...

探索GameFi:区块链与游戏的未来融合

在过去的几年里,区块链技术逐渐渗透到各个领域,为不同行业带来了前所未有的变革。其中,游戏行业成为了一个引人注目的焦点,而这种结合被称为GameFi,即游戏金融。GameFi不仅仅是一个概念,更是一场区块链和游…...

Windows下使用CMake编译lua

Lua 是一个功能强大、高效、轻量级、可嵌入的脚本语言。它支持程序编程、面向对象程序设计、函数式编程、数据驱动编程和数据描述。 Lua的官方网站上只提供了源码,需要使用Make进行编译,具体的编译方法为 curl -R -O http://www.lua.org/ftp/lua-5.4.6.…...

【C语言(十一)】

C语言内存函数 一、memcpy使用和模拟实现 void * memcpy ( void * destination, const void * source, size_t num ); • 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。 • 这个函数在遇到 \0 的时候并不会停下来。 • 如果sourc…...

系统运行占用过高

1、CPU过高的问题排查 示例代码: public class Test { static class MyThread extends Thread { public void run() { // 死循环,消耗CPU int i 0; while (true) { i; } } } public static void main(String args[]) throws InterruptedException { ne…...

HTML---初识CSS

文章目录 前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 一.CSS概念 CSS是层叠样式表(Cascading Style Sheets)的缩写。它是一种用于描述HTML文档外观样式的标记语言。通过CSS,开发者可以在不改变HTML标记结构的情况…...

监控pod 容器外网请求网络带宽,过滤掉内网、基于k8spacket开发、prometheus开发export

首先安装k8spacket 安装k8spacket遇到问题,下载插件一直能不能下载成功,pod不能启动。所有手动下载处理。 helm repo add k8spacket https://k8spacket.github.io/k8spacket-helm-chart helm pull k8spacket/k8spacket打开values.yaml 文件 手动下载插…...

windows下docker环境安装

开启硬件虚拟化技术 win10中开启 Hyper-V Win10 下是否开启硬件虚拟化技术,在控制面板,启用 window 功能,找到 Hyper-V 选项,点勾选确认。如图: Windows 11 家庭中文版新增 Hyper-V选项 注意以下的解决方案来自win1…...

Python小程序 - 表格数值统计

题设:Excel表格中,计算如下图所示不同颜色(蓝、黄、桔)单元格值:各颜色填涂的单元格值的总和条件: - Excle表格中 - 分色标记,单元格有值 - 开始列(当前为D),…...

Unity | Shader基础知识(第一集:unity中最简单的shader)

目录 一、unity的shader 二、创建一个shader(在创建时,选前三种都可以) 三、内容解读 1.shader一直都在 2.我们写shader在写什么 四、没有被干预的shader(最简单的shader) 相关阅读 编写着色器概述 - Unity 手册…...

橘子学K8S01之容器中所谓的隔离

我们一直都在说容器就是一个沙盒,沙盒技术顾名思义就是像一个集装箱一样,把应用(服务,进程之类的)装起来的技术,这样每个进程在自己的沙盒中和其他的沙盒隔离开来,每个沙盒之间存在一个边界使得他们互不干扰&#xff0…...

利用svm进行模型训练

一、步骤 1、将文本数据转换为特征向量 : tf-idf 2、使用这些特征向量训练SVM模型 二、代码 from sklearn.model_selection import train_test_split from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.svm import SVC from sklearn.m…...

【Docker】WSL 2 上的 Docker 搭建和入门

▒ 目录 ▒ 🛫 导读开发环境 1️⃣ 安装安装Docker Desktop for Windows 2️⃣ 环境配置3️⃣ hello world第一次运行再次运行分析总结 📖 参考资料 🛫 导读 开发环境 版本号描述文章日期2023-12-14操作系统Win11 - 22H222621.2715WSL2 C:…...

pytorch环境配置

1.创建环境 conda create --name pytorch python3.11.5 2.激活环境 source activate pytorch 3.添加国内镜像源: conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ conda config --add channels https://mirrors.tuna.tsin…...

电子眼+无人机构建平安城市视频防控监控方案

电子眼(也称为监控摄像机)可以通过安装在城市的不同角落,实时监控城市的各个地方。它们可以用于监测交通违法行为、监控公共场所的安全以及实时监测特定区域的活动情况。通过电子眼的应用,可以帮助警方及时发现并响应各类安全事件…...

mysql binlog_ignore_db参数的效果详解

​ 我们知道 binlog 会记录数据库所有执行的 DDL 和 DML 语句(除了数据查询语句select、show等)。 我们可以在mysql配置文件中关闭binlog [mysqld] skip-log-bin注意默认情况下会记录所有库的操作,那么如果我们有另类需求,比如说只让某个库记录 binglog 或排除某个库记录…...

HI3559AV100和FPGA 7K690T的PCIE接口调试记录-续

上文https://blog.csdn.net/fzktongyong/article/details/134963814?spm1001.2014.3001.5501 上一篇文中PCIE实测速度和理论计算有较大偏差,经过尝试后有所提升。 1、提升效果 1)、RC写操作,实测速度817MB/s(410407&…...

我的LVDS信号有振铃?可能是端接电阻没选对!从仿真到实测的端接方案选择指南

LVDS信号振铃问题全解析:从端接电阻选择到实测验证 振铃现象是LVDS信号传输中最令人头疼的问题之一。当你在示波器上看到信号边沿出现振荡波形时,第一反应可能是怀疑PCB布局或信号源质量。但经验丰富的工程师都知道,80%的振铃问题根源在于端接…...

【图灵完备(Turing Complete)】五、从逻辑门到LEG:指令集与条件跳转的构建

1. 从逻辑门到处理器:LEG架构的诞生之路 记得我第一次用面包板搭建简单逻辑电路时,连个LED灯闪烁都要折腾半天。而现在我们要做的,是把这些基础逻辑门像乐高积木一样拼接成真正的处理器核心。LEG架构的设计初衷就是要解决原始图灵机指令宽度受…...

Halcon图像高效转换:HObject到Bitmap的优化实践(20ms内完成)

1. 为什么需要HObject到Bitmap的高效转换 在工业视觉和深度学习应用中,Halcon的HObject图像格式和Windows平台的Bitmap格式就像两个说着不同语言的人。我遇到过太多这样的场景:当我们需要把Halcon处理后的图像交给TensorFlow做推理,或者要在…...

AML启动器:智能管理XCOM 2模组的一站式解决方案

AML启动器:智能管理XCOM 2模组的一站式解决方案 【免费下载链接】xcom2-launcher The Alternative Mod Launcher (AML) is a replacement for the default game launchers from XCOM 2 and XCOM Chimera Squad. 项目地址: https://gitcode.com/gh_mirrors/xc/xcom…...

告别“瞎测”:如何用Tessent ATPG生成高效测试向量(Pattern)提升芯片良率

芯片测试效率革命:Tessent ATPG实战指南与良率提升策略 在半导体行业,每一纳秒的测试时间缩减都可能转化为数百万美元的成本节约。当芯片设计进入7nm以下工艺节点时,制造缺陷导致的良率问题愈发突出,传统测试方法已无法满足现代芯…...

Emby Premiere完全免费解锁终极教程:简单三步享受高级媒体服务器功能

Emby Premiere完全免费解锁终极教程:简单三步享受高级媒体服务器功能 【免费下载链接】emby-unlocked Emby with the premium Emby Premiere features unlocked. 项目地址: https://gitcode.com/gh_mirrors/em/emby-unlocked 你是否曾经为Emby Premiere的高级…...

宇视NVR接入AS-V1000平台全流程指南(含SDK端口配置避坑)

宇视NVR对接AS-V1000平台实战手册:从配置到排障的深度解析 当监控系统需要整合多品牌设备时,宇视NVR与AS-V1000平台的对接成为典型场景。不同于标准化的协议对接,SDK接入方式往往隐藏着诸多"暗礁"——从端口冲突到能力集匹配&#…...

Loop:让Mac窗口管理效率倍增的效率神器

Loop:让Mac窗口管理效率倍增的效率神器 【免费下载链接】Loop MacOS窗口管理 项目地址: https://gitcode.com/GitHub_Trending/lo/Loop 你是否也曾在多任务处理时,被杂乱无章的窗口搞得焦头烂额?切换应用时总要在一堆窗口中寻找目标&a…...

基于DAMOYOLO-S与计算机网络技术:构建分布式视频分析集群

基于DAMOYOLO-S与计算机网络技术:构建分布式视频分析集群 想象一下,一个大型物流园区,上百个摄像头日夜不停地运转,管理者需要实时知道:哪条通道拥堵了?哪个区域有异常人员闯入?传统的监控方式…...

Bud错误处理终极指南:构建健壮Web应用的10个最佳实践

Bud错误处理终极指南:构建健壮Web应用的10个最佳实践 【免费下载链接】bud The Full-Stack Web Framework for Go 项目地址: https://gitcode.com/gh_mirrors/bu/bud Bud作为Go语言的全栈Web框架,其错误处理机制直接影响应用的稳定性和用户体验。…...