当前位置:主页 > 网页前端 > JavaScript代码 >

浅谈Webpack是如何打包CommonJS的

时间:2022-08-02 09:20:38 | 栏目:JavaScript代码 | 点击:

CommonJS 是 Node 中的一种模块化规范,其是一种运行在 Node 环境下的代码,这种代码是不能直接运行到浏览器环境中的。但是在日常使用 webpack 的项目中不用做额外的处理,我们也能使用 CommonJS 来书写代码,那么 webpack 在这背后做了什么呢?

我们这里不看编译时,只看运行时

一、书写代码

使用yarn init -y命令初始化一个package.json文件。 接着yarn add webpack安装一下webpack。 目录下创建一个index.js内容如下:

const sum = require('./sum')

console.log(sum(1, 2))

sum.js文件内容如下:

module.exports = (...args) => args.reduce((x, y) => x + y, 0)

二、使用webpack打包编译

这里不想写webpack的配置文件然后再通过 webpack-cli 来打包,就直接写一个打包的文件。

// build.js
const webpack = require('webpack')

function f1() {
	return webpack({
		entry: './index.js',
		mode: 'none',
		output: {
			iife: false,
			pathinfo: 'verbose' // verbose: 冗余;尽可能的详细
		}
	})
}

f1().run((err, stat) => {
	console.log('打包')
})

接着在终端跑一下这个文件

node build.js

如果成功的话就会出来一个dist目录,里面有个main.js总共就是50行代码,其中大部分都是注释,代码如下

var __webpack_modules__ = ([
/* 0 */,
  /* 1 */
  /*!****************!*\
    !*** ./sum.js ***!
    \****************/
  /*! unknown exports (runtime-defined) */
  /*! runtime requirements: module */
  /*! CommonJS bailout: module.exports is used directly at 1:0-14 */
  ((module) => {
    module.exports = (...args) => args.reduce((x, y) => x + y, 0)
  })
]);
/************************************************************************/
// 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__ = {};
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
(() => {
  /*!******************!*\
    !*** ./index.js ***!
    \******************/
  /*! unknown exports (runtime-defined) */
  /*! runtime requirements: __webpack_require__ */
  const sum = __webpack_require__(/*! ./sum */ 1)

  console.log(sum(1, 2))
})();

三、解析

我们再把代码精简一下,并加上注释

// 存放的模块,是一个数组
const __webpack_modules__ = [
  ,
  ((module) => {
    // sum.js 中的内容
    module.exports = (...args) => args.reduce((x, y) => x + y, 0)
  })
]

// 模块缓存(也就是说如果模块已经被引用过了就直接从这儿拿)
const __webpack_module_cache__ = {}

// moduleId 为 __webpack_modules__ 的下标
function __webpack_require__(moduleId) {
  // 如果能从缓存里面拿到,则直接返回
  const cachedModule = __webpack_module_cache__[moduleId]
  if (cachedModule !== undefined) return cachedModule.exports
  
  // 缓存内拿不到,则创建一个对象同时内部包含一个 exports 对象并存入到缓存内
  const module = __webpack_module_cache__[moduleId] = {
    exports: {}
  }
  
  // 接着通过执行 __webpack_modules__  中的moduleId对应函数并传入 module 对象
  // 通过函数内赋值 module.exports 获得 sum 函数
  __webpack_modules__[moduleId](module, module.exports, __webpack_require__)
  
  // 最后返回 module 中的 exports 对象
  return module.exports
}

(() => {
  // index.js 中的内容
  const sum = __webpack_require__(1)

  console.log(sum(1, 2))
})();

我们通过注释配合来解析一下

您可能感兴趣的文章:

相关文章