webpack cjs运行时分析示例详解

作者:豆芽不吃豆 时间:2024-04-19 09:51:56 

准备工作(接上篇文章的示例也可以):

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行)

webpack cjs运行时分析示例详解

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://blog.csdn.net/lucky569/article/details/128444422

标签:webpack,cjs,运行时
0
投稿

猜你喜欢

  • Python学习之str重要函数

    2022-12-29 05:46:37
  • 浅谈keras 模型用于预测时的注意事项

    2022-10-16 13:23:04
  • python实现批量转换图片为黑白

    2023-03-14 15:13:11
  • Pytorch-LSTM输入输出参数方式

    2021-02-22 18:49:28
  • python 函数内部修改外部变量的方法

    2022-05-24 09:04:19
  • 关于element-ui中el-form自定义验证(调用后端接口)

    2024-04-27 15:57:00
  • SQL常用数据库操作命令使用方法

    2007-08-22 13:24:00
  • 替换python字典中的key值方法

    2022-10-20 04:03:34
  • Mysql建库字符集和排序规则及说明

    2024-01-15 14:04:13
  • PHPMailer发送HTML内容、带附件的邮件实例

    2024-05-11 10:07:43
  • Python连接phoenix的方法示例

    2023-05-24 06:25:19
  • Python中的hypot()方法使用简介

    2021-06-02 03:44:37
  • 基于python3 OpenCV3实现静态图片人脸识别

    2022-10-04 20:59:30
  • ASP的数据命名有什么规则吗?

    2009-10-28 18:23:00
  • Python换行与不换行的输出实例

    2022-01-15 13:10:10
  • 详解操作python容器的内置通用函数

    2022-12-09 04:52:39
  • asp下实现代码的“运行代码”“复制代码”“保存代码”功能源码

    2011-04-14 10:39:00
  • Python使用multiprocessing实现一个最简单的分布式作业调度系统

    2022-06-14 07:43:33
  • Django RestFramework 全局异常处理详解

    2023-12-15 03:16:42
  • PyCharm 2020.1版安装破解注册码永久激活(激活到2089年)

    2022-06-20 13:08:13
  • asp之家 网络编程 m.aspxhome.com