# Mode 配置
此处只是简单的提一下 Mode 配置选项
- 默认值:production(什么都不设置的情况下)
- 可选值: 'none' | 'development' | 'production'
三种选项值的区别
选项 | 描述 |
---|---|
development | 会将DefinePlugin 中process.env.NODE_ENV 的值设置为development 。为模块和 chunk 启用有效的名。 |
production | 会将DefinePlugin 中process.env.NODE_ENV 的值设置为production 。为模块和 chunk 启用确定性的混淆名称。FlagDependencyUsagePlugin ,FlagIncludedChunksPlugin ,ModuleConcatenationPlugin ,NoEmitOnErrorsPlugin 和TerserPlugin 。 |
none | 不使用任何默认优化选项 |
使用
module.exports = {
mode: 'development',
};
1
2
3
2
3
# Webpack 的模块化
Webpack 打包的代码,允许我们使用各种各样的模块化,但是最常用的是CommonJS
和ES Module
先写一个ESModule规范和一个CommonJS规范的模块
// format.js CommonJS
const dateFormat = data => {
return "2021-07-04"
}
const priceFormat = price => {
return "100.00"
}
module.exports = { dateFormat, priceFormat }
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
// math.js ES Module
export const sum = (num1, num2) => {
return num1 + num2
}
export const mul = (num1, num2) => {
return num1 * num2
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# Webpack 对于 CommonJS 模块化实现原理分析
编译前代码
const { dateFormat, priceFormat } = require("./js/format")
console.log(dateFormat("abc"))
console.log(priceFormat("abc"))
1
2
3
4
2
3
4
编译后代码
// 定义了一个对象
// 模块的路径(key): 函数(value)
var __webpack_modules__ = {
"./src/js/format.js":
(function (module) {
const dateFormat = data => {
return "2021-07-04"
}
const priceFormat = price => {
return "100.00"
}
// * 将我们要导出的变量,放入到module对象中的exports对象中,同时也放入了__webpack_module_cache__缓存中
module.exports = { dateFormat, priceFormat }
})
};
// 定义一个对象,作为加载模块的缓存
var __webpack_module_cache__ = {};
// 是一个函数当我们加载一个模块时,都会通过这个函数来加载
function __webpack_require__(moduleId) {
// * 1. 获取参数对应的缓存值,判断缓存中是否已经加载过
var cachedModule = __webpack_module_cache__[moduleId];
if (cachedModule !== undefined) {
// * 如果缓存过就直接从缓存取
return cachedModule.exports;
}
// * 2. 给module遍历和__webpack_module_cache__[moduleId]赋值了同一个对象,以后就会共享变化(因为地址一样)
var module = __webpack_module_cache__[moduleId] = { exports: {} };
// * 加载执行模块
__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
// * 4. 导出module.exports {dateFormat, priceFormat }
return module.exports;
}
var __webpack_exports__ = {};
// * 加!立即执行函数的一种写法,1. (function () {})() 2. (function () {}()) 3. !function() {}()
// * 默认情况下定的的function无法直接运行,采用取反将其变成表达式后,就可以使用立即执行
// todo 此处开始执行,前面在定义
!function () {
// * 加载./src/js/format
// todo 从__webpack_require__获取到返回值({dateFormat, priceFormat })然后将其解构
const { dateFormat, priceFormat } = __webpack_require__("./src/js/format.js")
// todo 然后调用上面解构的函数
console.log(dateFormat("abc"))
console.log(priceFormat("abc"))
}();
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
52
53
54
55
56
57
58
59
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
52
53
54
55
56
57
58
59
# Webpack 对于 ES Module 模块化实现原理分析
编译前代码
import { sum, mul } from "./js/math"
console.log(sum(20, 30))
console.log(mul(20, 30))
1
2
3
4
2
3
4
编译后代码
// 1. 定义了一个对象,对象里面放的是我们的模块映射
var __webpack_modules__ = ({
"./src/js/math.js":
(function (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
// * 调用r,记录是一个__esModule -> true
__webpack_require__.r(__webpack_exports__);
// * exports对象本身是没有对应的函数
__webpack_require__.d(__webpack_exports__, {
"sum": function () { return sum; },
"mul": function () { return mul; }
});
const sum = (num1, num2) => {
return num1 + num2
}
const mul = (num1, num2) => {
return num1 * num2
}
})
});
// * 模块的缓存
var __webpack_module_cache__ = {};
// * 3. require函数的实现(加载模块)
function __webpack_require__(moduleId) {
var cachedModule = __webpack_module_cache__[moduleId];
if (cachedModule !== undefined) {
return cachedModule.exports;
}
var module = __webpack_module_cache__[moduleId] = {
exports: {}
};
__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
return module.exports;
}
// * 立即执行函数
!function () {
// * 函数本身也是一个对象,给__webpack_require__这个函数添加一个d属性,它的值是一个function
__webpack_require__.d = function (exports, definition) {
// * 遍历传入的对象
for (var key in definition) {
// * 调用o判断definition和exports是否有key这个属性
if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
// * definition有且exports没有这个属性
// * 就给exports定义key这个属性,设置为可枚举的并重写get方法
// * 该get方法相当于做了一个代理,当我们exports[key]调用时,实际回去访问definition[key]
Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
}
}
};
}();
!function () {
// * 给__webpack_require__这个函数添加一个o属性,它的值是一个function
// * 用于判断obj中是否有prop这个属性
__webpack_require__.o = function (obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
}();
!function () {
// * 给__webpack_require__这个函数添加一个r属性,它的值是一个function
__webpack_require__.r = function (exports) {
if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
// * 如果支持Symbol的话
// * 给exports添加一个Symbol.toStringTag属性,告诉其是一个模块
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
}
// * 给exports添加一个__esModule属性,标记加载的是一个ES Module
Object.defineProperty(exports, '__esModule', { value: true });
};
}();
var __webpack_exports__ = {};
!function () {
// * 调用r,记录是一个__esModule -> true
__webpack_require__.r(__webpack_exports__);
// * 本质就是调用__webpack_modules__的./src/js/math.js属性,它是一个函数
// * _js_math__WEBPACK_IMPORTED_MODULE_0__就等于exports
var _js_math__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/js/math.js");
// * 下面的语法相当于func(20, 30)
console.log((0, _js_math__WEBPACK_IMPORTED_MODULE_0__.sum)(20, 30))
console.log((0, _js_math__WEBPACK_IMPORTED_MODULE_0__.mul)(20, 30))
}();
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
注意:在Es Module的实现中,exports中实际上只是获取了一个代理,只是在访问时调用get去获取definition中对应的函数
# CommonJS和ESModule混合使用
// es module导出内容,commonJs导入内容
const { sum, mul } = require("./js/math")
// CommonJS导出内容,es module导入内容
import { dateFormat, priceFormat } from "./js/format"
console.log(sum(20, 30))
console.log(mul(20, 30))
console.log(dateFormat("aaa"))
console.log(priceFormat("bbb"))
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
var __webpack_modules__ = ({
"./src/js/format.js":
(function (module) {
const dateFormat = data => {
return "2021-07-04"
}
const priceFormat = price => {
return "100.00"
}
module.exports = { dateFormat, priceFormat }
}),
"./src/js/math.js":
(function (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {
"sum": function () { return sum; },
"mul": function () { return mul; }
});
const sum = (num1, num2) => {
return num1 + num2
}
const mul = (num1, num2) => {
return num1 * num2
}
})
});
var __webpack_module_cache__ = {};
function __webpack_require__(moduleId) {
var cachedModule = __webpack_module_cache__[moduleId];
if (cachedModule !== undefined) {
return cachedModule.exports;
}
var module = __webpack_module_cache__[moduleId] = {
exports: {}
};
__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
return module.exports;
}
!function () {
// * 给__webpack_require__这个函数添加一个n属性,是一个函数
// * 判断当前这个module是不是Es Module, 如果是就加给module加一个default再返回,如果不是就直接返回
__webpack_require__.n = function (module) {
var getter = module && module.__esModule ?
function () { return module['default']; } :
function () { return module; };
// * 调用d给getter代理一下
__webpack_require__.d(getter, { a: getter });
return getter;
};
}();
!function () {
__webpack_require__.d = function (exports, definition) {
for (var key in definition) {
if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
}
}
};
}();
!function () {
__webpack_require__.o = function (obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
}();
!function () {
__webpack_require__.r = function (exports) {
if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
}
Object.defineProperty(exports, '__esModule', { value: true });
};
}();
var __webpack_exports__ = {};
!function () {
"use strict";
// * 调用r,告诉当前是一个Es Module
__webpack_require__.r(__webpack_exports__);
// * 加载format
// CommonJS导出内容,es module导入内容
var _js_format__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/js/format.js");
var _js_format__WEBPACK_IMPORTED_MODULE_0___default = __webpack_require__.n(_js_format__WEBPACK_IMPORTED_MODULE_0__);
// ES module导出内容,CommonJS导入内容
const { sum, mul } = __webpack_require__("./src/js/math.js");
console.log(sum(20, 30))
console.log(mul(20, 30))
console.log(_js_format__WEBPACK_IMPORTED_MODULE_0___default().dateFormat("aaa"))
console.log(_js_format__WEBPACK_IMPORTED_MODULE_0___default().priceFormat("bbb"))
}();
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
分析
- 可以看到在webpack中无论ES Module还是CommonJS都是公用同一个调用函数__webpack_require__
- 当我们直接解构获取导出的内容(使用CommonJS语法导入)时,编译出来也是使用解构的
- 而使用ESModule导入的内容就算使用“解构语法”(实际不是解构),编译出来的结果也不是解构的而是使用对象
.
获取,个人分析是因为ESModule导入时使用了代理(此处代理是指重写getter,并没给其赋值,而是访问的时候调用getter去获取别的地方的值)的方式,所以不能解构 - 但是CommonJS导入,ES Module导出时好像也有一次代理(疑问。。)