浅谈Webpack是如何打包CommonJS的

目录
  • 一、书写代码
  • 二、使用webpack打包编译
  • 三、解析

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

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

  • 首先执行立即执行函数(L32)中的__webpack_require__函数,并传入moduleId 为 1
  • __webpack_require__函数中尝试在__webpack_module_cache__中获取moduleId为 1 的模块(L16)
  • __webpack_module_cache__中获取失败之后创建一个object,同时内部有属性exports = {},并同时将其赋值给__webpack_module_cache__[moduleId](L20)
  • 执行对应的moduleId的函数__webpack_modules__[moduleId],同时将module对象作为入参,在函数内将sum函数赋值给参数module.exports对象(L6),如此module.exports就是sum函数了
  • 然后在__webpack_require__中返回 module.exports
  • 执行完__webpack_require__(1)以后将其返回值赋值给sum(L34)
  • 最后就可以调用sum函数了(L36)

到此这篇关于浅谈Webpack是如何打包CommonJS的的文章就介绍到这了,更多相关Webpack打包CommonJS内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 利用webpack理解CommonJS和ES Modules的差异区别

    前言 问: CommonJS 和 ES Modules 中模块引入的区别? CommonJS 输出的是一个值的拷贝:ES Modules 生成一个引用,等到真的需要用到时,再到模块里面去取值,模块里面的变量,绑定其所在的模块. 我相信很多人已经把这个答案背得滚瓜烂熟,好,那继续提问. 问:CommonJS 输出的值是浅拷贝还是深拷贝? 问:你能模拟实现 ES Modules 的引用生成吗? 对于以上两个问题,我也是感到一脸懵逼,好在有 webpack 的帮助,作为一个打包工具,它让 ES Mod

  • webpack4.x CommonJS模块化浅析

    先看下webpack官方文档中对模块的描述: 在模块化编程中,开发者将程序分解成离散功能块(discrete chunks of functionality),并称之为模块. 每个模块具有比完整程序更小的接触面,使得校验.调试.测试轻而易举. 精心编写的模块提供了可靠的抽象和封装界限,使得应用程序中每个模块都具有条理清楚的设计和明确的目的. webpack 的核心概念之一就是一切皆模块,webpack 在项目中的作用就是,分析项目的结构,找到 JavaScript 模块以及其他一些浏览器不能直接

  • 浅谈Webpack是如何打包CommonJS的

    目录 一.书写代码 二.使用webpack打包编译 三.解析 CommonJS 是 Node 中的一种模块化规范,其是一种运行在 Node 环境下的代码,这种代码是不能直接运行到浏览器环境中的.但是在日常使用 webpack 的项目中不用做额外的处理,我们也能使用 CommonJS 来书写代码,那么 webpack 在这背后做了什么呢? 我们这里不看编译时,只看运行时 一.书写代码 使用yarn init -y命令初始化一个package.json文件. 接着yarn add webpack安装

  • 浅谈webpack性能榨汁机(打包速度优化)

    最近对项目的本地开发环境进行了打包速度优化,原有项目,网上能搜到的优化方案基本都加了,在16年低配mac pro 上打包时间为25秒多,但我发现细节做一些调整可能大大降低打包时间,最终优化到7秒多 dll 原有项目是线上和本地公用一套dll配置,因为antd这类ui库需要按需加载所以不能放到dll中,这时可以单独写一个dll配置,将所有第三方库添加到dll中. 这时因为.babelrc中添加了babel-plugin-import插件会导致优化不生效,所以需要对开发环境单独配置babel opt

  • 浅谈webpack打包之后的文件过大的解决方法

    以前一直使用 create-react-app 这个脚手架进行 react 开发,后面因为一些自定义的配置,转而使用 webpack 搭建一套自己的脚手架.但是在使用 webpack 打包之后发现,纳尼?怎么文件这么大??? 于是研究了一下如何处理 webpack 打包之后文件太大的情况,简单记录下来. 首先配置全局变量 首先,通过指定环境,告诉 webpack 我们当前处于 production 环境中,要按照 production 的方式去打包. //指定环境,将process.env.NO

  • 浅谈webpack打包生成的bundle.js文件过大的问题

    问题 使用webpack进行打包时,发现bundle.js竟然有2M多. 解决办法 网上有去除插件.提取第三方库.压缩代码等方法. 还有一个比较容易忽略的原因就是开了sourcemap 在生产环境中,应使用devtool: false 关闭sourcemap后bundle.js的大小从2.46M降到302k 以上这篇浅谈webpack打包生成的bundle.js文件过大的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们. 您可能感兴趣的文章: 彻底解决 webpa

  • 浅谈webpack打包过程中因为图片的路径导致的问题

    最近在制作一个自己的个人博客的时候遇到这么一个问题, 在CSS中使用了相对路径来充当背景图片, 如下所示: 然后将整个工程使用webpack打包之后, 在浏览器上运行却报错了, 报错如下: 也就是说, 打包之后这个图片文件找不到了, 那么原因出在哪里呢? 先来看一下我在webpack.config.js文件中的配置: 在这里其实我的loader并没有使用错误的, 图片对应的就是使用url-loader来处理. 那么再来看一下通过webpack打包之后的目录: 发现dist文件夹中出现了我们想要打

  • 浅谈webpack构建工具配置和常用插件总结

    webpack构建工具已经火了好几年,也是当下狠火狠方便的构建工具,我们没有理由不去学习.既然选择webpack就要跟着时代走,我们要追随大牛的步伐,大牛等等我. 一.webpack基础 在根目录使用npm init 命令创建package.json,创建过程中一路回车. 本地安装webpack命令:npm install webpack webpack-cli --save-dev 安装成功后写入package.js的devDependencies中,可以通过 npm node_modules

  • 浅谈webpack下的AOP式无侵入注入

    说起来, 面向切面编程(AOP)自从诞生之日起,一直都是计算机科学领域十分热门的话题,但是很奇怪的是,在前端圈子里,探讨AOP的文章似乎并不是多,而且多数拘泥在给出理论,然后实现个片段的定式)难免陷入了形而上学的尴尬境地,本文列举了两个生产环境的实际例子论述webpack和AOP预编译处理的结合,意在抛砖引玉.当然,笔者能力有限,如果有觉得不妥之处,还请大家积极的反馈出来, 共同进步哈. 重要的概念 AOP: 面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. Joi

  • 浅谈将JNI库打包入jar文件

    在Java开发时,我们有时候会接触到很多本地库,这样在对项目打包的时候我们不得不面临一个选择:要么将库文件与包好的jar文件放在一起:要么将库文件包入jar. 将一个不大的项目包成一个jar有诸多发布优势,本次将分享一个将JNI包入jar的方法. [实现思路] 将JNI库(dll.so等)包入jar后,我们无法通过路径来访问它们,而库的读取依赖一个java.library.path下对应名称的外部库文件,我们仅仅需要在调用JNI前将其由jar包释放出来,这类似于文件的拷贝过程. [部署位置的选取

  • 浅谈Java 将图片打包到jar中的路径问题

    Eclipse使用导出Jar包后打开加载不了图像? 出现这种问题的原因大多是因为路径的问题,往往是在项目中运行正常,但是一旦打包成Jar后就不能正常显示了,下面总结一下解决此类问题的方法: 一.通过使用外部资源文件的方式解决 把项目打包生成Jar后,再新建一文件夹,把项目中所有使用的图片文件和生成Jar文件放在该目录下,只要代码对图片文件的引用路径正确,如:ImageIcon image=new ImageIcon(SwingResourceManager.getImage("icons/log

  • 浅谈Vue 自动化部署打包上线

    应用场景 项目打包后发布到正式环境,需要后端配合或者前端自己上传到服务器上,操作不便且容易产生问题,比如后台不在的情况而前台没有服务器的信息,这时发布就被延:或者前端自己上传容易导致误操作,如果上传错地方没正确上传都可能导致线上直接崩掉,而这对于已发布的产品而言是致命的.因此,有必要实现自动化部署代码到线上,解放双手的同时也减轻后端兄弟的压力. 项目使用 1.在项目根目录下, 创建 deploy/products.js 文件 /* *读取env环境变量 */ const SERVER_ID =

随机推荐