2.1. eval
eval 会将每个module模块,执行eval,执行后不会生成sourcemap文件,仅仅是在每个模块后,增长sourceURL来关联模块处理先后对应的关系。在webpack中配置devtool: 'eval', 以下打包后的代码:javascript
(function(modules) { // webpackBootstrap "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return printMe; });\n\nfunction printMe() {\n console.log('11111111');\n}\n\n//# sourceURL=webpack:///./js/demo1.js?"); /***/ "./js/main.js": /*!********************!*\ !*** ./js/main.js ***! \********************/ /*! no exports provided */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _demo1_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./demo1.js */ \"./js/demo1.js\");\n\n\nconsole.log('main.js');\n\n//# sourceURL=webpack:///./js/main.js?"); }) })
如上打包后的代码,每个打包后的模块后面都增长了包含sourceURL的注释,sourceURL的值是压缩前存放的代码的位置,这样就经过sourceURL关联了压缩先后的代码。并无为每个模块生成相对应的sourcemap。css
优势是:打包速度很是快,由于不须要生成sourcemap文件。
缺点是:因为会映射到转换后的代码,而不是映射到原始代码,因此不能正确的显示行数。html
2.2 source-mapvue
在webpack中配置加上 devtool: 'source-map' 配置完成后,source-map会为每个打包后的模块生成独立的sourcemap文件,好比在package.json文件中 这样配置:java
"scripts": { "build": "webpack --progress --colors --devtool source-map" }
而后运行 npm run build 后,会在dist目录下生产map文件。咱们继续打包后的代码以下:webpack
(function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony import */ var _demo1_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./demo1.js */ "./js/demo1.js"); __webpack_require__(/*! ../styles/main.css */ "./styles/main.css"); console.log('main.js'); /***/ }), /***/ "./styles/main.css": /*!*************************!*\ !*** ./styles/main.css ***! \*************************/ /*! no static exports found */ /***/ (function(module, exports) { // removed by extract-text-webpack-plugin /***/ }) /******/ }); //# sourceMappingURL=bundle.js.map
如上打包后的代码最后面一句代码是 //# sourceMappingURL=bundle.js.map ,同时在dist目录下会针对每个模块生成响应的 .map文件,
好比咱们在dist目录中会生成 bundle.js.map文件,咱们能够打开看下这个文件代码会以下:web
{ "version":3, "sources":[ "webpack:///webpack/bootstrap","webpack:///./js/demo1.js", "webpack:///./js/main.js","webpack:///./styles/main.css" ], "names":["printMe","console","log","require"], "mappings":";AAAA;AACA;;AAEA;AACA...", "file":"bundle.js", "sourcesContent":[], "sourceRoot": "" }
上面生成后的map文件是一个javascript对象,能够被解析器读取,它主要有如下几个属性:chrome
version: Source Map 的版本,目前为3.
sources: 转换前的文件,该项是一个数组,表示可能存在多个文件合并.
names: 转换前的全部变量名和属性名。
mappings: 记录位置信息的字符串。
sourcesContent: 转换前的文件内容列表,与sources列表依次对应。
sourceRoot: 转换前的文件所在的目录,若是与转换前的文件在同一个目录,该项为空。npm
chrome和firefox如何使用Source Map呢?json
1. 开启开发者工具
使用快捷键 option + command + i; 或者在 菜单栏选择视图 -> 开发者 -> 开发者工具。
2. 打开设置
点击右上角的三个点的图标,选择Settings, 以下图所示:
3. 开启Source Map
在Sources中,选中 Enable Javascript source maps 以下图所示
开启完成后,咱们在 package.json 配置以下代码:
scripts: { "dev": "webpack-dev-server --progress --colors --devtool source-map --hot --inline", }
而后在main.js 代码中,添加以下代码:
require('../styles/main.css'); import demo1Func from './demo1.js'; console.log('main.js'); console.log(a)
如上a未定义,直接打印a,确定会报错的。咱们在命令行中 运行 npm run dev 后,打开页面会发现报错,报错以下:
而后咱们点击 main.js:5 后,会进入main.js代码内,以下图:
2.3 inline(好比 inline-source-map)
该属性不会生成独立的 .map文件,而是将 .map文件以dataURL的形式插入。
以下代码:
/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony import */ var _demo1_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./demo1.js */ "./js/demo1.js"); __webpack_require__(/*! ../styles/main.css */ "./styles/main.css"); console.log('main.js'); console.log(a); /***/ }), /***/ "./styles/main.css": /*!*************************!*\ !*** ./styles/main.css ***! \*************************/ /*! no static exports found */ /***/ (function(module, exports) { // removed by extract-text-webpack-plugin /***/ }) /******/ }); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2Vz.....
inline-source-map 使用缺点:它会使得bundle.js文件变得很是大,由于它须要把 sourceMappingURL 以dataurl的形式插入到bundle.js里面去。以下图所示:
2.4 cheap(如:cheap-source-map)
该属性在打包后一样会为每个文件模块生成 .map文件,可是与source-map的区别在于cheap生成的 map文件会忽略原始代码中的列信息;
好比生成后的bundle.js.map中的mappings的代码以下:
"mappings":";AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;AClFA;AAAA;AAAA;AACA;AACA;AACA;;;;;;;;;;
如上能够看到,它不会生成列的信息,有逗号就表示包含了列信息。增长该属性后,cheap就不会生成列信息,调式代码列信息没有什么用,所以使用cheap后,文件大小相对于source-map来说,bundle.js 文件会变得更小。
以下图使用的是 source-map 生成的bundle.js.map 文件, 会包含列的信息,以下图所示:
使用cheap属性后,也不会有loader模块之间对应的sourcemap,由于webpack打包最终会将全部的非js资源,经过loader形式转换成js资源,好比 vue 中的文件,xx.vue -> vue-loader转换 -> js -> 压缩 -> 压缩后的js
因此说若是没有loader之间的sourcemap文件的话,那么在debug的时候,定义到压缩前的js中的时候,不能跟踪到vue中。
2.5 module(如:cheap-module-source-map)
该属性的配置也是生成一个没有列的信息的sourceMaps文件,同时loader的sourcemap也被简化成为只包含对应行的。
三:开发环境和线上环境如何选择sourceMap?
从上面的eval, inline, source-map, cheap, module中能够看到,各自属性值表明打包后的具体含义,所以咱们能够分析下开发环境和正式环境要如何选择sourceMap;咱们能够从以下几个方面考虑:
1. 源代码中的列信息是没有任何做用,所以咱们打包后的文件不但愿包含列相关信息,只有行信息能创建打包先后的依赖关系。所以无论是开发环境或生产环境,咱们都但愿添加cheap的基本类型来忽略打包先后的列信息。
2. 无论是开发环境仍是正式环境,咱们都但愿能定位到bug的源代码具体的位置,好比说某个vue文件报错了,咱们但愿能定位到具体的vue文件,所以咱们也须要module配置。
3. 咱们须要生成map文件的形式,所以咱们须要增长 source-map属性。
4. 咱们介绍了eval打包代码的时候,知道eval打包后的速度很是快,由于它不生成map文件,可是能够对eval组合使用 eval-source-map使用会将map文件以DataURL的形式存在打包后的js文件中,好比以下:
它的效果相似于inline的效果,所以在正式环境中不要使用 eval-source-map, 由于它会增长文件的大小,可是在开发环境中,能够试用下,由于他们打包的速度很快。
所以咱们能够总结以下:
在开发环境中咱们可使用
module.exports = { devtool: 'cheap-module-eval-source-map' }
在正式环境中咱们可使用
module.exports = { devtool: 'cheap-module-source-map'; }
如上是总结的在开发环境和正式环境使用的sourcemap进行打包的简单思路。