webpack打包原理解析

时间:2025-02-23 12:39:59

文章目录

    • webpack打包是如何运行的
      • webpack对CommonJS的模块化处理
      • webpack对es6 Module模块化的处理
    • webpack文件的按需加载
      • 按需加载输出代码分析
    • 总结

webpack打包是如何运行的

  • 也可以称为,webpack是如何实现模块化的
  • CommonJS是同步加载模块,一般用于node。因为node应用程序运行在服务器上,程序通过文件系统可以直接读取到各个模块的文件,特点是响应快速,不会因为同步而阻塞了程序的运行;
  • AMD是异步加载模块,所以普遍用于前端。而前端项目运行在浏览器中,每个模块都要通过http请求加载js模块文件,受到网络等因素的影响如果同步的话就会使浏览器出现“假死”(卡死)的情况,影响到了用户体验。
  • ESModule 旨在实现前后端模块化的统一。而webpack就是把ES6的模块化代码转码成CommonJS的形式,从而兼容浏览器的。
  • 为什么webpack打包后的文件,可以用在浏览器:此时webpack会将所有的js模块打包到中(异步加载的模块除外,异步模块后面会讲),读取到了内存里,就不会再分模块加载了。
  • webpack将代码打包成什么样子

webpack对CommonJS的模块化处理

  • 举例:
    • 文件,引入文件
    const foo = require('./foo');
    
    (foo);
    ('我是高级前端工程师~');
    
    • 文件
     = {
      name: 'quanquan',
      job: 'fe',
    };
    
  • 当我们执行webpack之后,打包完成,可以看到内的代码
// modules 即为存放所有模块的数组,数组中的每一个元素都是一个函数
(function(modules) {
	// 安装过的模块都存放在这里面
    // 作用是把已经加载过的模块缓存在内存中,提升性能
	var installedModules = {};
	// 去数组中加载一个模块,moduleId 为要加载模块在数组中的 index
    // __webpack_require__作用和  中 require 语句相似
	function __webpack_require__(moduleId) {
		// require 模块时先判断是否已经缓存, 已经缓存的模块直接返回
		if(installedModules[moduleId]) {
			return installedModules[moduleId].exports;
		}
		// 如果缓存中不存在需要加载的模块,就新建一个模块,并把它存在缓存中
		var module = installedModules[moduleId] = {
            // 模块在数组中的index
            i: moduleId,
            // 该模块是否已加载完毕
            l: false,
            // 该模块的导出值,也叫模块主体内容, 会被重写
			exports: {}
		};
		// 从 modules 中获取 index 为 moduleId 的模块对应的函数
        // 再调用这个函数,同时把函数需要的参数传入,this指向模块的主体内容
		modules[moduleId].call(, module, , __webpack_require__);
		// 将模块标记为已加载
		 = true;
		// 返回模块的导出值,即模块主体内容
		return ;
	}
    // 向外暴露所有的模块
	__webpack_require__.m = modules;
	// 向外暴露已缓存的模块
    __webpack_require__.c = installedModules;
	
	...
	...
	
    // Webpack 配置中的 publicPath,用于加载被分割出去的异步代码,这个暂时还没有用到
	__webpack_require__.p = "";
    // Load entry module and return exports
    // 准备工作做完了, require 一下入口模块, 让项目跑起来
    // 使用 __webpack_require__ 去加载 index 为 0 的模块,并且返回该模块导出的内容
    // index 为 0 的模块就是 文件,也就是执行入口模块
    // __webpack_require__.s 的含义是启动模块对应的 index
	return __webpack_require__(__webpack_require__.s = 0);
})
/***** 华丽的分割线 上边时 webpack 初始化代码, 下边是我们写的模块代码 *******/
// 所有的模块都存放在了一个数组里,根据每个模块在数组的 index 来区分和定位模块
([
	/* 模块 0 对应  */
	(function(module, exports, __webpack_require__) {
		// 通过 __webpack_require__ 规范导入 foo 函数, 对应的模块 index 为 1
		const foo = __webpack_require__(1);
		
		(foo);
		('我是高级前端工程师~');
	}),
	/* 模块 1 对应  *