webpack模块化原理 webpack打包的代码 允许我们使用各种模块化 如最常用的CommonJS ES Module
CommonJS模块化实现原理; 使用commonjs 后 webpack打包好的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 var __webpack_modules__ = { "./src/js/format.js" : (function (module ) { const dateFormat = (date ) => { return "2020-12-12" ; } const priceFormat = (price ) => { return "100.00" ; } module .exports = { dateFormat, priceFormat } }) } var __webpack_module_cache__ = {};function __webpack_require__ (moduleId ) { if (__webpack_module_cache__[moduleId]) { return __webpack_module_cache__[moduleId].exports; } var module = __webpack_module_cache__[moduleId] = { exports : {} }; __webpack_modules__[moduleId](module , module .exports, __webpack_require__); return module .exports; } !function ( ) { const { dateFormat, priceFormat } = __webpack_require__("./src/js/format.js" ); console .log(dateFormat("abc" )); console .log(priceFormat("abc" )); }();
ES Module模块化实现原理 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 var __webpack_modules__ = { "./src/es_index.js" : (function (__unused_webpack_module, __webpack_exports__, __webpack_require__ ) { __webpack_require__.r(__webpack_exports__); var _js_math__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/js/math.js" ); console .log(_js_math__WEBPACK_IMPORTED_MODULE_0__.mul(20 , 30 )); console .log(_js_math__WEBPACK_IMPORTED_MODULE_0__.sum(20 , 30 )); }), "./src/js/math.js" : (function (__unused_webpack_module, __webpack_exports__, __webpack_require__ ) { __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 ) { if (__webpack_module_cache__[moduleId]) { return __webpack_module_cache__[moduleId].exports; } var module = __webpack_module_cache__[moduleId] = { exports : {} }; __webpack_modules__[moduleId](module , module .exports, __webpack_require__); return module .exports; } !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 }); }; }(); __webpack_require__("./src/es_index.js" );
ES Module 和 CommonJS相互调用 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 var __webpack_modules__ = ({ "./src/index.js" : (function (__unused_webpack_module, __webpack_exports__, __webpack_require__ ) { "use strict" ; __webpack_require__.r(__webpack_exports__); 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__); const math = __webpack_require__("./src/js/math.js" ); console .log(math.sum(20 , 30 )); console .log(math.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" )); }), "./src/js/format.js" : (function (module ) { const dateFormat = (date ) => { return "2020-12-12" ; } const priceFormat = (price ) => { return "100.00" ; } module .exports = { dateFormat, priceFormat } }), "./src/js/math.js" : (function (__unused_webpack_module, __webpack_exports__, __webpack_require__ ) { __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 ) { if (__webpack_module_cache__[moduleId]) { return __webpack_module_cache__[moduleId].exports; } var module = __webpack_module_cache__[moduleId] = { exports : {} }; __webpack_modules__[moduleId](module , module .exports, __webpack_require__); return module .exports; } !function ( ) { __webpack_require__.n = function (module ) { var getter = module && module .__esModule ? function ( ) { return module ['default' ]; } : function ( ) { return module ; }; __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 }); }; }(); __webpack_require__("./src/index.js" );
Source-map 当我们使用webpack打包时 在浏览器运行的代码是通过打包压缩的
真实跑在浏览器上的代码和我们编写的代码是有差异的
Es6代码会转成ES5 对应的代码行号列号也会不同
代码进行丑化压缩时, 会将编码名称修改
当我们代码报错需要调试时 调试转换后的代码是很困难
source-map 是从已转换的代码映射到原始的源文件
使浏览器可以重构原始源并在调试器中显示重建的原始源
source-map 的使用 使用source-map分为两个步骤
webpack.config.js中的devtool选项控制是否生成以及如何生成sourcemap
第一步:根据源文件,生成source-map文件,webpack在打包时,可以通过配置生成source-map;
第二步:在转换后的代码,最后添加一个注释,它指向sourcemap;
//# sourceMappingURL=common.bundle.js.map
浏览器会根据我们的注释,查找响应的source-map,并且根据source-map还原我们的代码,方便进行调试。
在chrome浏览器中 我们可以手动打开source-map(当然默认情况下是打开的
source-map的分析 目前的source-map长什么样子
version:当前使用的版本,也就是最新的第三版;
sources:从哪些文件转换过来的source-map和打包的代码(最初始的文件);
names:转换前的变量和属性名称(因为我目前使用的是development模式,所以不需要保留转换前的名称);
mappings:source-map用来和源文件映射的信息(比如位置信息等),一串base64 VLQ(veriablelength quantity可变长度值)编码;
file:打包后的文件(浏览器加载的文件);
sourceContent:转换前的具体代码信息(和sources是对应的关系);
sourceRoot:所有的sources相对的根目录;
MDN参考 https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/SourceMap.jsm
生成source-map devtool有很多的选项处理source-map; https://webpack.docschina.org/configuration/devtool/
选择不同的值生成的source-map会稍微有差异 打包过程也会有性能的差异 根据不同情况进行选择
不会生成source-map的值
false: 不使用source-map,也就是没有任何和source-map相关的内容。
none: production模式下的默认值,不生成source-map。
eval: development模式下的默认值(什么值都不写),不生成source-map
但是它会在eval执行的代码中,添加 //# sourceURL=;
它会被浏览器在执行时解析,并且在调试面板中生成对应的一些文件目录,方便我们调试代码;
eval 的 效果