Webpack入门,模块打包原理分析

面对工程中成百上千个模块,Webpack究竟是如何将它们有序地组织在一起,并按照开发者预想的顺序运行在浏览器上的呢?本篇文章将通过一个简单的示例。分析一下Webpack模块打包的原理。

// example.js
module.exports = {
  add: function(a,b) {
    return a + b;
  }
}
// index.js
const example = require("./example.js");
const sum = example.add(5,6);
console.log("sum:",sum);

上面的代码经过Webpack打包后将会成为如下的形式(为了易读性,删除了些注释的代码):


(() => {
  var __webpack_modules__ = ({
    "./src/example.js": ((module) => {
      eval("module.exports = {\r\n  add: function (a, b) {\r\n    return a + b;\r\n  },\r\n};\r\n\n\n//# sourceURL=webpack://webpack-demo/./src/example.js?");
}),

    "./src/index.js":((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
      eval("const example = __webpack_require__(/*! ./example.js */ \"./src/example.js\");\r\nconst sum = example.add(5, 6);\r\nconsole.log(\"sum:\", sum);\r\n\n\n//# sourceURL=webpack://webpack-demo/./src/index.js?");
 })
});

// 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__ = __webpack_require__("./src/index.js");

})();

这是一个最简单的Webpack打包结果。但是已经可以清晰地展示出它如何将具有依赖关系的模块串联在一起的。

上面的打包结果分为以下几个部分。

  • 最外层匿名函数。它用来包裹整个打包结果,并构成自身的作用域。
  • __webpack_modules__对象。工程中所有产生了依赖关系的模块都会以key-value的形式放在这里。key可以理解为一个模块的id,由数字或者一个很短的hash字符串构成;value则是由一个匿名函数包裹的模块实体,匿名函数的参数赋予了每个模块导出和导入的能力。
  • __webpack_module_cache__对象。每个模块只在第一次被加载的时候执行,之后其导出值就被存储到这个对象里面,当再次被加载的时候webpack会直接从这里取值,而不会重新执行该模块。
  • __webpack_require__函数。对模块加载的实现,在浏览器中可以通过调用__webpack_require__(moduleId)来完成模块的导入。
  • __webpack_exports__对象。它的作用是加载入口模块并返回导出值。

下面分析一下,打包的结果如何在浏览器中执行的。

  1. 在最外层匿名函数中初始化浏览器执行环境,包括定义__webpack_module_cache__对象、__webpack_require__函数等,为模块的加载和执行做一些准备工作。
  2. 加载入口模块。每个打包结果有且仅有一个入口哦模块,在上面的示例中,index.js是入口模块,在浏览器中会从它开始执行。
  3. 执行模块代码。如果执行到了module.exports则记录下模块的导出值;如果中间遇到require函数(即__webpack_require__),则会暂时交出执行权,进入__webpack_require__函数体内进行加载其他模块的逻辑。
  4. 在__webpack_require__中判断即将加载的模块是否存在于__webpack_module_cache__中。如果存在则直接取值,否则执行该模块的代码获取导出值。
  5. 所有依赖的模块都已经执行完毕,最后执行权又回到入口模块。当入口模块的代码执行完毕,也就意味着整个文件运行结束。

提示

通过分析,可以看出,代码运行的第三步和第四步是一个递归的过程。Webpack为每个模块创造了一个可以导出和导入的环境,但本质上并没有修改代码的执行逻辑,因此代码执行的顺序与模块加载的顺序是完全一致的,这也是Webpack模块打包额奥秘。

示例代码仓库

https://gitee.com/zero_79152105/webpack-vblog

原创文章,作者:ZERO,如若转载,请注明出处:https://www.edu24.cn/course/webpack-module-bundle.html

Like (0)
Donate 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
ZEROZERO
Previous 2022年11月14日
Next 2022年11月18日

相关推荐

  • Java自学之异常的捕获与处理

    在程序开发中,程序的编译与运行是两个不同的阶段,编译主要针对的是语法检测,而在程序运行时却有可能出现各种各样的错误导致程序中断执行,那么这些错误在Java中统一称为异常。 异常处理…

    2020年12月11日
    1.2K
  • Java自学之内部类

    内部类是一种常见的嵌套结构,利用这样的结构使得内部类可以与外部类共存,并且方便地进行私有操作的访问。 内部类基本概念 内部类(内部定义普通类、抽象类、接口的统称)是指一种嵌套的结构…

    2020年12月14日
    1.3K
  • Java自学之多线程编程

    多线程编程是Java语言最为重要的特性之一。利用多线程技术可以提升单位时间内的程序处理性能,也是现代程序开发中高并发的主要设计模式。 进程与线程 进程是一个应用程序。线程是一个进程…

    2020年12月16日
    1.4K
  • vue3.0项目如何配置路径别名

    vue更新到3.0以后,在项目中已经深度集成了webpack,使用vue create命令新建项目之后,已经没有webpack配置文件了,这对于像小编这样没有系统学习过前端的同学来…

    2020年8月22日
    3.9K
  • CSS布局之圣杯与双飞翼布局

    所谓圣杯布局和双飞翼布局其实解决的问题是相同的,都是解决左右两栏固定宽度,中间部分自适应,其中某部分内容比其他内容高的时候,保证三者元素等高。他俩的区别就是:圣杯用padding。…

    2019年6月18日
    1.8K
  • Java自学之I/O编程

    I/O(Input/Output,输入/输出)可以实现数据的读取与写入操作,Java针对I/O操作的实现提供了java.io工具包,此包的核心组成由File类、InputStrea…

    2020年12月21日
    1.1K
  • spring boot练习篇之用户登录系统【接入数据库】

    抛弃JSP,只做纯粹的前后端分离项目。 写在前面 学习基础知识是枯燥无味的,之所以会这样,多数是因为心不静,对于如何运用它,感到茫然。所以建议大家在学习Java基础知识的时候,一定…

    2021年5月28日
    1.1K
  • Webpack入门,模块打包之ES6 Module

    JavaScript之父Brendan Eich在最初设计这门语言时,并没有包含模块的概念。基于越来越多的工程需要,为了使用模块化进行开发,JavaScript社区涌现出了多种模块…

    2022年11月11日
    439
  • Java自学之继承

    在面向对象的设计过程中,类是基本的逻辑单位。但是对于这些基本的逻辑单位需要考虑到重用的设计问题,所以在面向对象的设计里提供有继承,并利用这一特点实现类的可重用性定义。 类继承定义 …

    2020年12月3日
    1.2K
  • Webpack入门,CSS Modules

    CSS Modules是近年来比较流行的一种开发模式,其理念就是把CSS模块化,让CSS也拥有模块的特点,具体如下: 使用CSS Modules时不需要额外安装模块,只要开启css…

    2022年11月28日
    672