写作不易,未经作者允许禁止以任何形式转载! 如果觉得文章不错,欢迎关注、点赞和分享!掘金原文链接
Webpack模块化
CommonJS:
打包前
const { dateFormat, priceFormat } = require ('./js/format' );console .log(dateFormat("abc" ));console .log(priceFormat("abc" ));
打包后
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
打包前
import { sum, mul } from "./js/math" ;console .log(mul(20 , 30 ));console .log(sum(20 , 30 ));
打包后
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混合导入导出
打包前
const { sum, mul } = require ("./js/math" );import { dateFormat, priceFormat } from "./js/format" ;console .log(sum(20 , 30 ));console .log(mul(20 , 30 ));console .log(dateFormat("aaa" ));console .log(priceFormat("bbb" ));console .log(abc);
打包后
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" );
总结
原理都是类似的
通过一个webpack_module对象来存储模块化代码
通过webpack_module_cache来缓存模块化代码
通过webpack_require来从webpack_module_cache或webpack_module中读取并从引入代码
认识Source-Map
参考文档
如何使用SourceMap
第一步:根据源文件,生成source-map文件,webpack在打包时,可以通过配置生成source-map;
devtool:'source-map'
第二步:在转换后的代码,最后添加一个注释,它指向sourcemap;
//# sourceMappingURL=common.bundle.js.map
浏览器会根据我们的注释,查找相应的source-map,并且根据source-map还原我们的代码,方便进行调试。
在Chrome中,我们可以按照如下的方式打开source-map:
√Enable JavaScript source maps
√Enable CSS source maps
最初source-map生成的文件带下是原始文件的10倍,第二版减少了约50%,第三版又减少了50%,所以目前一个 133kb的文件,最终的source-map的大小大概在300kb。
目前的source-map长什么样子?
version:当前使用的版本,也就是最新的第三版;
sources:从哪些文件转换过来的source-map和打包的代码(最初始的文件);
names:转换前的变量和属性名称(因为目前使用的是development模式,所以不需要保留转换前的名称);
mappings:source-map用来和源文件映射的信息(比如位置信息等),一串base64 VLQ(veriable- length quantity可变长度值)编码;
file:打包后的文件(浏览器加载的文件);
sourceContent:转换前的具体代码信息(和sources是对应的关系);
sourceRoot:所有的sources相对的根目录;
生成SourceMap
如何在使用webpack打包的时候,生成对应的source-map?
下面几个值不会生成source-map
false:不使用source-map,也就是没有任何和source-map相关的内容。
none:production模式下的默认值(什么值都不写),不生成source-map。
eval:development模式下的默认值,不生成source-map
但是它会在eval执行的代码中,添加 //# sourceURL=;
它会被浏览器在执行时解析,并且在调试面板中生成对应的一些文件目录,方便我们调试代码;
使用source-map的值
source-map
生成独立的source-map文件,并在打包后的JS文件中有一个注释指向source-map文件;
注释: `` //# sourceMappingURL=bundle.js.map`
eval-source-map
source-map以DataUrl的形式添加到eval函数后面
inline-source-map
source-map以DataUrl的形式添加到打包后的JS文件后面(注释)
cheap-source-map:
会生成source-map,但是会更加高效一些(cheap低开销),因为它没有生成列映射(Column Mapping)
因为在开发中,我们只需要行信息通常就可以定位到错误了
cheap-module-source-map:
会生成source-map,类似于cheap-source-map,但是对源自loader的source-map处理会更好。
对源自loader的source-map处理会更好,官方也没有给出很好的解释 其实是如果loader对我们的源码进行了特殊的处理,比如babel,会恢复成源文件的代码模块格式,例如不会删除自定义的空行。
hidden-source-map:
会生成sourcemap,但是不会对source-map文件进行引用;
相当于删除了打包文件中对sourcemap的引用注释
# sourceMappingURL=bundle.js.map
如果手动添加进来,那么source-map就会生效了
nosources-source-map:
会生成sourcemap,但是生成的sourcemap只有错误信息的提示,不会生成源代码文件;
点击错误信息也无法查看源码
多个值的组合
那么在开发中,最佳的实践是什么呢?
掘金原文链接
掘金:前端LeBron
知乎:前端LeBron
持续分享技术博文,关注微信公众号👇🏻