webpack

webpack 是一个开源的JavaScritpt模块打包工具,其最核心的功能是解决模块之间的依赖,将各个模块按照特定的规则和顺序组织在一起,这个过程叫做模块打包

模块打包原理

一个最简单的Webpack打包结果(bundle)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// index.js
const calculator = require('./calculator.js');
const sum = calculator.add(2, 3);
console.log('sum', sum);

// calculator.js
module.exports = {
add: function(a, b) {
return a + b;
}
};

// 立即执行匿名函数
(function(modules) {
//模块缓存
var installedModules = {};
// 实现require
function __webpack_require__(moduleId) {
...
}
// 执行入口模块的加载
return __webpack_require__(__webpack_require__.s = 0);
})({
// modules:以key-value的形式存储所有被打包的模块
0: function(module, exports, __webpack_require__) {
// 打包入口
module.exports = __webpack_require__("3qiv");
},
"3qiv": function(module, exports, __webpack_require__) {
// index.js内容
},
jkzz: function(module, exports) {
// calculator.js 内容
}
});
  1. 最外层的匿名函数中初始化浏览器执行环境,包括定义installedModules对象、__webpack_require__函数等,为模块的加载做一些准备工作
  2. 加载入口模块,每个bundle都有且只有一个入口模块,在上面的例子中,index.js是入口模块,在浏览器中会从它开始执行
  3. 执行模块代码.如果执行到了modle.exports则记录下模块的导出值;如果中间遇到了require函数(准确地说是__webpack_require__),则会暂时交出执行权,进入__webpack_require__函数体内进行加载其他模块的逻辑
  4. 在**webpack_require中判断即将加载的模块是否存在于installedModule**中.如果存在直接取值,否则回到第三步,执行该模块的代码来获取导出值
  5. 所有的依赖都已执行完毕,最后执行权又回到入口模块.当入口代码执行完毕,也就意味着整个bundle运行结束.

第三步和第四步是一个递归的过程,webpack为每个模块创造来一个可以导出和导入模块的环境,但是本质上并没有修改代码的执行逻辑,因此代码执行的顺序和模块加载的顺序是完全一致的.

面对工程中成百上千的模块webpack如何将它们有序的组织在一起,了解一些webpack的核心概念

  • 入口
  • 输出
  • loader
  • 插件
  • 模式
  • 浏览器兼容性
  • 环境

entry 入口

在一切流程的最开始,我们需要指定一个或多个入口(entry),也就是告诉Webpack具体从源码目录下的哪个文件开始打包。如果把工程中各个模块的依赖关系当作一棵树,那么入口就是这棵依赖树的根