【webpack】cjs运行时分析

news2025/1/21 3:01:01

准备工作(接上篇文章的示例也可以):
1. 在index.js文件中引入任一js文件

import sum from './sum';

const result = sum(1,2);
console.log(result);

2. sum文件

const sum = (a, b) => {
  return a+b;
}

export default sum

3. build.js文件

const path = require('path');
const webpack = require('webpack');

function wrapBuild() {
  return webpack({
    entry: './index.js',
    mode: 'none',
    output: {
      path: path.resolve(__dirname, 'build'),
      filename: '[name].js'
    },
    infrastructureLogging: {
      debug: true,
      level: 'log',
    }
  })
}

wrapBuild().run((err, stat) => {
  const startTime = stat.startTime;
  const endTime = stat.endTime;
  console.log('构建时间: ', endTime - startTime);
})

4. 命令行执行node ./build.js 生成打包产物main.js。(截图未完整, 共87行)
在这里插入图片描述
5. 什么是运行时代码?
通过webpack打包得到的文件(如/build/main.js的骨架代码), 其中包含了一些webpack如何将多个模块集合在一起的代码, 可粗暴理解为webpack runtime 打包过后的代码。可通过node build/main.js可直接调试。

6. 示例打包js资源后的运行时代码分析:(含注解)

/******/ (() => { // webpackBootstrap
/******/ 	"use strict";
/******/ 	var __webpack_modules__ = ([
/* 0 */,    // ---模块0, 入口模块 可以理解为index.js模块
/* 1 */    // ---模块1,打包过后的sum.js
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
const sum = (a, b) => {
  return a+b;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (sum);

/***/ })
/******/ 	]);
/************************************************************************/
/******/ 	// 模块缓存
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// 模块加载器, 模拟实现common.js的require
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// 根据moduleId从缓存中读取module
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
            // 若缓存中存在该模块,则返回当前的module.exports
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// 缓存中不存在该模块,则去__webpack_modules__里取。
                // 创建一个新的模块,  写入cache对象, key为moduleId, value 为 exports对象
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// 调用包裹函数,计算模块信息,解析出相关模块内容(如:exports)
/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/ 	
/******/ 		// 返回当前解析过后的module.exports
/******/ 		return module.exports;
/******/ 	}

var __webpack_exports__ = {};
// 加载入口函数
(() => {
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _sum__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
const result = (0,_sum__WEBPACK_IMPORTED_MODULE_0__["default"])(1,2);
console.log(result);
})();

/******/ })()
;

该运行时代码一共做了三件事:

  • __webpack_modules__ : 维护一个所有模块的数组,通过深度优先遍历将其全部转换为AST,以供给后面的包裹函数解析
  • __webpack_require__: 手动实现一个模块加载器;优先从缓存列表__webpack_module_cache__中读取模块,并返回其exports内容。如果缓存中没有,则调用包裹函数解析出模块exports等重要内容,存入缓存列表中并返回exports。
  • 调用__webpack_require_(0): 运行入口模块.

7. 疑问?

  • 如果不对模块进行缓存,会有什么问题?
    模块内容重复计算,消耗性能。
    每个模块只在第一次引用的时候产生一个对象,后面都是引用该对象,减少代码复杂度。

  • module.exports和exports有什么区别?
    默认情况下,Node准备的exports变量和module.exports变量实际上是同一个变量,并且初始化为空对象,我们可以把要输出的东西直接加入在这个空对象里面;但是,如果我们要输出的是一个函数或数组,那么,只能给module.exports赋值,给exports赋值是无效的,因为赋值后,module.exports仍然是空对象。
    结论:
    如果要输出一个键值对象{},可以利用exports这个已存在的空对象{},并继续在上面添加新的键值;
    如果要输出一个函数或数组,必须直接对module.exports对象赋值。
    建议直接对module.exports赋值,可以应对任何情况;
    详细的可移步阮一峰大佬的文章:https://www.liaoxuefeng.com/wiki/1022910821149312/1023027697415616

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

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

相关文章

离子交换法深度剖析

离子交换法 是一种借助于离子交换剂上的离子和污水中的离子进行交换反应而除去污水中有害离子的方法。 离子交换法的特点 离子交换过程是一种特殊的吸附过程,在许多方面与吸附过程类似。 与吸附法比较,其特点是:它主要吸附污水中的离子化物质&#xff…

怎样做一个不会被淘汰的车载诊断工程师

步入中年,不可避免会接触到所谓的中年危机,时刻在提醒自己提高自己的护城河,增强核心竞争力。但是这种事情也不是靠空想,还是要功夫下在平时。 自己是在2016年开始接触车载诊断方面,从事过诊断范畴的开发、测试、偏系…

程序员的圣诞节是怎么样的?

2022年圣诞节到来啦,很高兴这次我们又能一起度过~ 一、前言 圣诞节,先在这里祝大家圣诞节快乐~~,用英语来表达就是 Merry Christmas ~~, 为了贴合这个氛围,今天分享种用 Python 绘制圣诞树的方法。 最近用代码绘画圣诞…

非常易用的网络路径中的网络延迟测试和监控以及自动发送报告工具

非常易用的网络路径中的网络延迟测试和监控以及自动发送报告工具。 作为网络管理员或网络工程师,时刻关注网络的交付速度至关重要。不仅需要确保自己有良好的响应时间,还需要确保网络的速度足以满足用户通信所需的每一条路径。而手动测试每个路径将占用…

SpringBoot+Vue项目医院体检中心管理系统

文末获取源码 开发语言:Java 使用框架:spring boot 前端技术:JavaScript、Vue.js 、css3 开发工具:IDEA/MyEclipse/Eclipse、Visual Studio Code 数据库:MySQL 5.7/8.0 数据库管理工具:phpstudy/Navicat JD…

电脑文件数据恢复方法是什么?未备份电脑文件数据恢复的七种方法

在日常生活中,我们总会遇到这样或那样的事情,比如在使用电脑过程中出现文件数据丢失情况,那么在未备份文件下电脑文件数据丢失怎么恢复?电脑文件数据恢复方法有哪些?这里将根据不同情况分享不同的电脑文件数据恢复方法…

L05_课后练习_波士顿房价预测

波士顿房价预测 1.导入所需要的库 import numpy as np import pandas as pd import matplotlib.pyplot as plt import torch import random from sklearn.model_selection import train_test_split2.读入数据 feature pd.read_csv("../data/boston.csv") feature…

Postgresql源码(95)优化器关键数据结构实例

1 测试数据 drop table student; create table student(sno int primary key, sname varchar(10), ssex int); insert into student values(1, stu1, 0); insert into student values(2, stu2, 1); insert into student values(3, stu3, 1); insert into student values(4, st…

Linux的环境变量

目录 什么是环境变量? 那么如何添加自己的程序到命令行上,可以直接执行? 如何查看环境变量? 如何定义环境变量? C语言如何获取环境变量? 什么是环境变量? 在回答这个问题之前,可…

【Linux】之systemd与systemctl

文章目录一、systemd1. systemd 守护进程管理 Linux 的启动2. systemd 提供的功能:3. systemd 使用单元来管理不同类型的对象。4. 服务单元信息二、systemctl1. systemctl输出中的服务状态2. 列出servera上安装的所以服务单元3. 列出servera上所有活动和不活动的套接字单元4.1 …

存档鉴未来,新时代电子档案长期保存之道

(一)电子档案单套制是未来档案管理的趋势 在政府和企业端,办公体系的信息化,电子档案的单套制实施,极大地提高了事务办理的效率,同时节约了大量纸质文件的使用成本。 在政务领域,单套制的推行…

Day840.原子类-Java 并发编程实战

原子类 Hi,我是阿昌,今天学习记录的是关于原子类。 一个累加器的例子,示例代码如下: 在这个例子中,add10K() 这个方法不是线程安全的,问题就出在变量 count 的可见性和 count1 的原子性上。 可见性问题…

Java7的异常处理新特性addSuppressed()方法

学习使用Java7新语法try-with-resources,在查看编译文件时,接触到addSuppressed()方法。记录一下使用方式。 先来看一段代码: private static void testt() {try (InputStream is CatchTest.class.getClassLoader().getResourceAsStream(&…

ThinkPHP 多应用模式初探

还是很久以前用tp3.0开发过项目,之后就再没使用过,现在tp都更新到6了,与之前差距很大,需要重新练习掌握最新的tp框架使用及特性。 目录 1.安装框架 2.安装多应用模式扩展think-multi-app 3.目录结构修改并创建应用子目录 4.应…

年后市场将反弹?服装人做好这些准备,才能赚到2023年第一桶金!

目前,随着防疫政策精准落地、逐步放开,人们对疫情的科学认知不断更新,市场活跃度正逐步恢复。秦丝通过与数万服装老板沟通交流,发现新的模式也在渐渐兴起,国内服装市场将有望迎来反弹。 1、消费氛围活跃,市…

善网ESG周报(第六期)

ESG报告: 宁夏建投城运首份社会责任(ESG)报告正式发布 12月20日,宁夏建投城市运营管理有限公司发布首份ESG报告。报告显示,其公司将业务与环境保护、社会责任、公司治理相结合打造一条绿色发展道路。 国寿股权投资发…

滚动条基本样式设置

::-webkit-scrollbar 系列属性 详细使用说明 ::-webkit-scrollbar注意:如果没有设置滚动溢出的相关属性,滚动条样式系列属性不会生效(resize 除外)。属性 ::-webkit-scrollbar 整个滚动条。::-webkit-scrollbar-button 滚动条上的…

Vue3组件化开发(一)

文章目录p11 组件组件的拆分和嵌套组件的CSS作用域组件的通信父子组件的通信父组件传递给子组件props的对象用法非prop的attribute子组件传递给父组件案例p11 组件 组件的拆分和嵌套 推荐安装的VS Cdoe插件 组件的CSS作用域 组件的通信 父子组件的通信 父组件传递给子组件…

模型初始化

在深度学习模型训练中,权重初始值极为重要,一个好的初始值会使得模型收敛速度提高,使模型准确率更准确,一般情况下,我们不使用全零初始值训练网络,为了利于训练和减少收敛时间,我们需要对模型进…

从入门到项目实战 - Vue 计算属性用法解析

Vue 计算属性用法解析上一节:《Vue 监听器用法解析 》| 下一节:《Vue 样式绑定》jcLee95 邮箱 :291148484163.com CSDN 主页:https://blog.csdn.net/qq_28550263?spm1001.2101.3001.5343 本文地址:https://blog.…