webpack打包bundle.js文件代码分析

  目录

webpack这个打包工具,现在可以说很火,前一段时间为了优化公司项目,搞了一个月的gulp,说实在的,gulp的功能我感觉很强大了,而且用起来很灵活,最关键是简单,需要什么的时候直接弄个gulp任务,但是,使用场景很少了,由于之前的项目是php的,现在一般都用vue,react等,都已经集成了webpack,虽然说不用太多配置,但是需要配置的时候还是有的,所以,webpack研究一下也是有必要的,今天,复杂的先不说,只说说bundle.js这个文件里的代码都是干吗用的。

webpack打包bundle.js文件代码分析

一个入口,一个文件

首先,webpack.config.js配置文件是这样滴:

1
2
3
4
5
6
module.exports = {
entry:'./index.js',
output:{
filename:'bundle.js'
}
};

index.js内容是这样滴:

1
console.log('index');

最后再看看打完包后的bundle.js内容

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// bundle.js
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};

/******/ // The require function
/******/ function __webpack_require__(moduleId) {

/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;

/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };

/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

/******/ // Flag the module as loaded
/******/ module.loaded = true;

/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }


/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;

/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;

/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";

/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports) {

console.log('index');

/***/ }
/******/ ]);

我们来分析一下bundle.js这个文件

  • 1.整个内容是一个自执行函数,自执行函数传的参数是一个数组,数组里的元素是function函数,这个函数体的内容就是index.js文件的内容。
  • 2.在这个闭包函数中,__webpack_require_是模块加载函数,接收模块id(对,webpack中每个模块都会有一个独一无二的id,其实也就是在IIFE传参数组中的索引值(0,1,2…..)。
  • 3.真正执行module index里面语句的是个调用
    1
    2
    // Execute the module function
    modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

我们再来看一个例子

一个入口,两个文件,A依赖B

先贴出文件内容:

1
2
3
4
5
6
// a.js
var b = require('./b.js');

console.log('a');

b.b1();

1
2
3
4
5
6
7
8
// b.js
exports.b1 = function () {
console.log('b1')
};

exports.b2 = function () {
console.log('b2')
};
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
// bundle.js
/******/ (function(modules) { // webpackBootstrap
// 省略一大段...........
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {

var b = __webpack_require__(1);

console.log('a');

b.b1();


/***/ },
/* 1 */
/***/ function(module, exports) {

exports.b1 = function () {
console.log('b1')
};

exports.b2 = function () {
console.log('b2')
};

/***/ }
/******/ ]);

我们再来分析一下上面的代码。

  • 1.由于有两个文件,所以IIFE得参数为长度是2的数组,并按照require的顺序排列。
  • 2.IIFE函数体部分是一模一样的,也就是说再复杂的,多个依赖的文件,函数体部分也不变滴。
  • 3.module a发生了变化,因为a依赖b,所以在a中调用webpack加载模块的函数

    1
    2
    // 1是模块b的id
    var b = __webpack_require__(1);
  • 4.我们再来分析一下modules[moduleId].call(module.exports, module, module.exports, webpack_require);
    使用call是因为为了确保每个module中的this指向的是module本身。然后给它传__webpack_require函数是想让module有加载其他module的能力。

    其它情况

    其它的情况,比如多入口,多出口情况这里就不做过多分析,我也没搞明白,接下来准备手写一个简单的仿webpack打包工具。