一、Mode配置
这里要简单讲一下,后面还会提到它的其他用法。
Mode配置选项,可以告知webpack使用相应模式的内置优化:
- 默认值是production
- 可选值有:’none’ | ‘development’ | ‘production’
这几个选项有什么样的区别呢?

const path = require('path');const { CleanWebpackPlugin } = require('clean-webpack-plugin');const HtmlWebpackPlugin = require('html-webpack-plugin');module.exports = {mode: 'development',entry: './src/main.js',output: {filename: 'bundle.js',//__dirname,当前文件的上级目录的绝对路径path: path.resolve(__dirname, './build'),// assetModuleFilename: 'img/[name].[hash:6][ext]',},plugins: [new CleanWebpackPlugin(),new HtmlWebpackPlugin({title: 'webpack项目',}),],};
mode: 'development',这样编译完的代码不会进行压缩丑化。
Mode配置代表更多 ,后续再了解。
二、模块化原理
webpack支持CommoJS原理
// 定义了一个对象// 模块的路径(key): 函数(value)var __webpack_modules__ = {"./src/js/format.js":(function (module) {const dateFormat = (date) => {return "2020-12-12";}const priceFormat = (price) => {return "100.00";}// 将我们要导出的变量, 放入到module对象中的exports对象module.exports = {dateFormat,priceFormat}})}// 定义一个对象, 作为加载模块的缓存var __webpack_module_cache__ = {};// 是一个函数, 当我们加载一个模块时, 都会通过这个函数来加载function __webpack_require__(moduleId) {// 1.判断缓存中是否已经加载过if (__webpack_module_cache__[moduleId]) {return __webpack_module_cache__[moduleId].exports;}// 2.给module变量和__webpack_module_cache__[moduleId]赋值了同一个对象var module = __webpack_module_cache__[moduleId] = { exports: {} };// 3.加载执行模块__webpack_modules__[moduleId](module, module.exports, __webpack_require__);// 4.导出module.exports {dateFormat: function, priceForamt: function}return module.exports;}// 具体开始执行代码逻辑!function () {// 1.加载./src/js/format.jsconst { dateFormat, priceFormat } = __webpack_require__("./src/js/format.js");console.log(dateFormat("abc"));console.log(priceFormat("abc"));}();
webpack支持ES6 Module原理
// 1.定义了一个对象, 对象里面放的是我们的模块映射var __webpack_modules__ = {"./src/es_index.js":(function (__unused_webpack_module, __webpack_exports__, __webpack_require__) {// 调用r的目的是记录时一个__esModule -> true__webpack_require__.r(__webpack_exports__);// _js_math__WEBPACK_IMPORTED_MODULE_0__ == exportsvar _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__);// 调用了d函数: 给exports设置了一个代理definition// 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;}})};// 2.模块的缓存var __webpack_module_cache__ = {};// 3.require函数的实现(加载模块)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__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__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) {Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });}Object.defineProperty(exports, '__esModule', { value: true });};}();__webpack_require__("./src/es_index.js");
CommonJS与ES6 Module相互导入原理
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__);// es module导出内容, CommonJS导入内容const math = __webpack_require__("./src/js/math.js");// CommonJS导出内容, es module导入内容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__ = {};// The require functionfunction __webpack_require__(moduleId) {// Check if module is in cacheif (__webpack_module_cache__[moduleId]) {return __webpack_module_cache__[moduleId].exports;}// Create a new module (and put it into the cache)var module = __webpack_module_cache__[moduleId] = {// no module.id needed// no module.loaded neededexports: {}};// Execute the module function__webpack_modules__[moduleId](module, module.exports, __webpack_require__);// Return the exports of the modulereturn module.exports;}!function () {// getDefaultExport function for compatibility with non-harmony modules__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;};}();/* webpack/runtime/define property getters */!function () {// define getter functions for harmony exports__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] });}}};}();/* webpack/runtime/hasOwnProperty shorthand */!function () {__webpack_require__.o = function (obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }}();/* webpack/runtime/make namespace object */!function () {// define __esModule on exports__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
我们的代码通常运行在浏览器上时,是通过打包压缩的:
也就是真实跑在浏览器上的代码,和我们编写的代码其实是有差异的
- 比如ES6的代码可能被转换成ES5
- 比如对应的代码行号、列号在经过编译后肯定会不一致
- 比如代码进行丑化压缩时,会将编码名称等修改
- 比如我们使用了TypeScript等方式编写的代码,最终转换成JavaScript
但是,当代码报错需要调试时(debug),调试转换后的代码是很困难的,况且我们不能保证代码不出错,那么如何可以调试这种转换后不一致的代码呢?答案就是source-map
- source-map是从已转换(压缩后的)的代码,映射到原始的源文件(npm run build之前的)一种类型文件
- 使浏览器可以重构原始源并在调试器中显示重建的原始源
如何使用
第一步:根据源文件,生成source-map文件,webpack在打包时,可以通过配置生成source-map
devtool:'source-map'
第二步:在转换后的代码,最后添加一个注释,它指向sourcemap
//# sourceMappingURL=common.bundle.js.map
浏览器会根据我们的注释,查找相应的source-map,并且根据source-map还原我们的代码,方便进行调试。
正常情况下压缩丑化后,不使用source-map,报错后我们无法准确的找到错误处,尤其项目过大时。


使用source-map:
entry: './src/main.js',
devtool: 'source-map',

此时浏览器报错可以快速定位:


分析source-map
最初source-map生成的文件带下是原始文件的10倍,第二版减少了约50%,第三版又减少了50%,所以目前一个 133kb的文件,最终的source-map的大小大概在300kb。
目前的source-map长什么样子呢?
- version:当前使用的版本,也就是最新的第三版
- sources:从哪些文件转换过来的source-map和打包的代码(最初始的文件)
- names:转换前的变量和属性名称(因为我目前使用的是development模式,所以不需要保留转换前的名 称)
- mappings:source-map用来和源文件映射的信息(比如位置信息等),一串base64 VLQ(veriablelength quantity可变长度值)编码
- file:打包后的文件(浏览器加载的文件)
- sourceContent:转换前的具体代码信息(和sources是对应的关系)
- sourceRoot:所有的sources相对的根目录
{
"version": 3,
"file": "bundle.js",
"mappings": "kCAkBAA,SAASC,KAAKC,YAlBd,WACE,IAAIC,EAAUH,SAASI,cAAc,OACrCD,EAAQE,UAAY,CAAC,QAAS,WAAWC,KAAK,KAC9CH,EAAQI,UAAY,UAGpB,MAAMC,EAAQ,IAAIC,MAElBN,EAAQD,YAAYM,GAGpB,MAAME,EAAQV,SAASI,cAAc,OAKrC,OAJAM,EAAMC,MAAMC,MAAQ,QACpBF,EAAMC,MAAME,OAAS,QAErBV,EAAQD,YAAYQ,GACbP,EAEiBW,MCjBtBC,EAA2B,GAG/B,SAASC,EAAoBC,GAE5B,IAAIC,EAAeH,EAAyBE,GAC5C,QAAqBE,IAAjBD,EACH,OAAOA,EAAaE,QAGrB,IAAIC,EAASN,EAAyBE,GAAY,CAGjDG,QAAS,IAOV,OAHAE,EAAoBL,GAAUI,EAAQA,EAAOD,QAASJ,GAG/CK,EAAOD,S,+BCnBfG,QAAQC,ICCa,S",
"sources": [
"webpack://01_webpack_learn/./src/js/component.js",
"webpack://01_webpack_learn/webpack/bootstrap",
"webpack://01_webpack_learn/./src/main.js",
"webpack://01_webpack_learn/./src/js/math.js"
],
"sourcesContent": [
"function component() {\r\n let element = document.createElement('div');\r\n element.innerHTML = ['Hello', 'Webpack'].join(' ');\r\n element.className = 'content';\r\n\r\n //创建一个img标签\r\n const imgEL = new Image();\r\n // imgEL.src = require('../img/7.jpg').default;\r\n element.appendChild(imgEL);\r\n\r\n //创建一个div 设置背景图片\r\n const divEL = document.createElement('div');\r\n divEL.style.width = 200 + 'px';\r\n divEL.style.height = 200 + 'px';\r\n // divEL.className = 'bg-img';\r\n element.appendChild(divEL);\r\n return element;\r\n}\r\ndocument.body.appendChild(component());\r\n",
"// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n",
"import { message } from './js/math.js';\r\nimport './js/component.js'\r\nconsole.log(message);",
"// function sum(n1, n2) {\r\n// return n1 + n2;\r\n// }\r\nexport const message=\"Hello\""
],
"names": [
"document",
"body",
"appendChild",
"element",
"createElement",
"innerHTML",
"join",
"className",
"imgEL",
"Image",
"divEL",
"style",
"width",
"height",
"component",
"__webpack_module_cache__",
"__webpack_require__",
"moduleId",
"cachedModule",
"undefined",
"exports",
"module",
"__webpack_modules__",
"console",
"log"
],
"sourceRoot": ""
}
生成source-map
如何在使用webpack打包的时候,生成对应的source-map呢?
- webpack提供了非常多的选项(目前是26个),来处理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(
"function component() {\r\n let element = document.createElement('div');\r\n element.innerHTML = ['Hello', 'Webpack'].join(' ');\r\n element.className = 'content';\r\n\r\n //创建一个img标签\r\n const imgEL = new Image();\r\n // imgEL.src = require('../img/7.jpg').default;\r\n element.appendChild(imgEL);\r\n\r\n //创建一个div 设置背景图片\r\n const divEL = document.createElement('div');\r\n divEL.style.width = 200 + 'px';\r\n divEL.style.height = 200 + 'px';\r\n // divEL.className = 'bg-img';\r\n element.appendChild(divEL);\r\n return element;\r\n}\r\ndocument.body.appendChild(component());\r\n\n\n//# sourceURL=webpack://01_webpack_learn/./src/js/component.js?"
);

source-map
生成一个独立的source-map文件,并且在bundle文件中有一个注释,指向source-map文件
bundle文件中有如下的注释: //# sourceMappingURL=bundle.js.map
开发工具会根据这个注释找到source-map文件,并且解析
对应的就是上上面的source-map。
eval-source-map
生成sourcemap,但是source-map是以DataUrl添加到eval函数的后面
eval(
'__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "message": function() { return /* binding */ message; }\n/* harmony export */ });\n// function sum(n1, n2) {\r\n// return n1 + n2;\r\n// }\r\nconst message="Hello"//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvanMvbWF0aC5qcy5qcyIsIm1hcHBpbmdzIjoiOzs7O0FBQUE7QUFDQTtBQUNBO0FBQ08iLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8wMV93ZWJwYWNrX2xlYXJuLy4vc3JjL2pzL21hdGguanM/OWMzOSJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBmdW5jdGlvbiBzdW0objEsIG4yKSB7XHJcbi8vICAgcmV0dXJuIG4xICsgbjI7XHJcbi8vIH1cclxuZXhwb3J0IGNvbnN0IG1lc3NhZ2U9XCJIZWxsb1wiIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./src/js/math.js\n'
);
inline-source-map
会生成sourcemap,但是source-map是以DataUrl添加到bundle文件的后面
!(function () {
'use strict';
/*!*********************!*\
!*** ./src/main.js ***!
\*********************/
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _js_math_js__WEBPACK_IMPORTED_MODULE_0__ =
__webpack_require__(/*! ./js/math.js */ './src/js/math.js');
/* harmony import */ var _js_component_js__WEBPACK_IMPORTED_MODULE_1__ =
__webpack_require__(/*! ./js/component.js */ './src/js/component.js');
/* harmony import */ var _js_component_js__WEBPACK_IMPORTED_MODULE_1___default =
/*#__PURE__*/ __webpack_require__.n(
_js_component_js__WEBPACK_IMPORTED_MODULE_1__
);
console.log(_js_math_js__WEBPACK_IMPORTED_MODULE_0__.message);
})();
/******/
})();
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVuZGxlLmpzIiwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7O0FDbEJBO0FBQ0E7QUFDQTtBQUNPOzs7Ozs7VUNIUDtVQUNBOztVQUVBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBOztVQUVBO1VBQ0E7O1VBRUE7VUFDQTtVQUNBOzs7OztXQ3RCQTtXQUNBO1dBQ0E7V0FDQSxlQUFlLDRCQUE0QjtXQUMzQyxlQUFlO1dBQ2YsaUNBQWlDLFdBQVc7V0FDNUM7V0FDQTs7Ozs7V0NQQTtXQUNBO1dBQ0E7V0FDQTtXQUNBLHlDQUF5Qyx3Q0FBd0M7V0FDakY7V0FDQTtXQUNBOzs7OztXQ1BBLDhDQUE4Qzs7Ozs7V0NBOUM7V0FDQTtXQUNBO1dBQ0EsdURBQXVELGlCQUFpQjtXQUN4RTtXQUNBLGdEQUFnRCxhQUFhO1dBQzdEOzs7Ozs7Ozs7Ozs7Ozs7QUNOdUM7QUFDYjtBQUMxQixZQUFZLGdEQUFPLEUiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8wMV93ZWJwYWNrX2xlYXJuLy4vc3JjL2pzL2NvbXBvbmVudC5qcyIsIndlYnBhY2s6Ly8wMV93ZWJwYWNrX2xlYXJuLy4vc3JjL2pzL21hdGguanMiLCJ3ZWJwYWNrOi8vMDFfd2VicGFja19sZWFybi93ZWJwYWNrL2Jvb3RzdHJhcCIsIndlYnBhY2s6Ly8wMV93ZWJwYWNrX2xlYXJuL3dlYnBhY2svcnVudGltZS9jb21wYXQgZ2V0IGRlZmF1bHQgZXhwb3J0Iiwid2VicGFjazovLzAxX3dlYnBhY2tfbGVhcm4vd2VicGFjay9ydW50aW1lL2RlZmluZSBwcm9wZXJ0eSBnZXR0ZXJzIiwid2VicGFjazovLzAxX3dlYnBhY2tfbGVhcm4vd2VicGFjay9ydW50aW1lL2hhc093blByb3BlcnR5IHNob3J0aGFuZCIsIndlYnBhY2s6Ly8wMV93ZWJwYWNrX2xlYXJuL3dlYnBhY2svcnVudGltZS9tYWtlIG5hbWVzcGFjZSBvYmplY3QiLCJ3ZWJwYWNrOi8vMDFfd2VicGFja19sZWFybi8uL3NyYy9tYWluLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImZ1bmN0aW9uIGNvbXBvbmVudCgpIHtcclxuICBsZXQgZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xyXG4gIGVsZW1lbnQuaW5uZXJIVE1MID0gWydIZWxsbycsICdXZWJwYWNrJ10uam9pbignICcpO1xyXG4gIGVsZW1lbnQuY2xhc3NOYW1lID0gJ2NvbnRlbnQnO1xyXG5cclxuICAvL+WIm+W7uuS4gOS4qmltZ+agh+etvlxyXG4gIGNvbnN0IGltZ0VMID0gbmV3IEltYWdlKCk7XHJcbiAgLy8gaW1nRUwuc3JjID0gcmVxdWlyZSgnLi4vaW1nLzcuanBnJykuZGVmYXVsdDtcclxuICBlbGVtZW50LmFwcGVuZENoaWxkKGltZ0VMKTtcclxuXHJcbiAgLy/liJvlu7rkuIDkuKpkaXYg6K6+572u6IOM5pmv5Zu+54mHXHJcbiAgY29uc3QgZGl2RUwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcclxuICBkaXZFTC5zdHlsZS53aWR0aCA9IDIwMCArICdweCc7XHJcbiAgZGl2RUwuc3R5bGUuaGVpZ2h0ID0gMjAwICsgJ3B4JztcclxuICAvLyBkaXZFTC5jbGFzc05hbWUgPSAnYmctaW1nJztcclxuICBlbGVtZW50LmFwcGVuZENoaWxkKGRpdkVMKTtcclxuICByZXR1cm4gZWxlbWVudDtcclxufVxyXG5kb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGNvbXBvbmVudCgpKTtcclxuIiwiLy8gZnVuY3Rpb24gc3VtKG4xLCBuMikge1xyXG4vLyAgIHJldHVybiBuMSArIG4yO1xyXG4vLyB9XHJcbmV4cG9ydCBjb25zdCBtZXNzYWdlPVwiSGVsbG9cIiIsIi8vIFRoZSBtb2R1bGUgY2FjaGVcbnZhciBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX18gPSB7fTtcblxuLy8gVGhlIHJlcXVpcmUgZnVuY3Rpb25cbmZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcblx0Ly8gQ2hlY2sgaWYgbW9kdWxlIGlzIGluIGNhY2hlXG5cdHZhciBjYWNoZWRNb2R1bGUgPSBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX19bbW9kdWxlSWRdO1xuXHRpZiAoY2FjaGVkTW9kdWxlICE9PSB1bmRlZmluZWQpIHtcblx0XHRyZXR1cm4gY2FjaGVkTW9kdWxlLmV4cG9ydHM7XG5cdH1cblx0Ly8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSlcblx0dmFyIG1vZHVsZSA9IF9fd2VicGFja19tb2R1bGVfY2FjaGVfX1ttb2R1bGVJZF0gPSB7XG5cdFx0Ly8gbm8gbW9kdWxlLmlkIG5lZWRlZFxuXHRcdC8vIG5vIG1vZHVsZS5sb2FkZWQgbmVlZGVkXG5cdFx0ZXhwb3J0czoge31cblx0fTtcblxuXHQvLyBFeGVjdXRlIHRoZSBtb2R1bGUgZnVuY3Rpb25cblx0X193ZWJwYWNrX21vZHVsZXNfX1ttb2R1bGVJZF0obW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyk7XG5cblx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcblx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xufVxuXG4iLCIvLyBnZXREZWZhdWx0RXhwb3J0IGZ1bmN0aW9uIGZvciBjb21wYXRpYmlsaXR5IHdpdGggbm9uLWhhcm1vbnkgbW9kdWxlc1xuX193ZWJwYWNrX3JlcXVpcmVfXy5uID0gZnVuY3Rpb24obW9kdWxlKSB7XG5cdHZhciBnZXR0ZXIgPSBtb2R1bGUgJiYgbW9kdWxlLl9fZXNNb2R1bGUgP1xuXHRcdGZ1bmN0aW9uKCkgeyByZXR1cm4gbW9kdWxlWydkZWZhdWx0J107IH0gOlxuXHRcdGZ1bmN0aW9uKCkgeyByZXR1cm4gbW9kdWxlOyB9O1xuXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmQoZ2V0dGVyLCB7IGE6IGdldHRlciB9KTtcblx0cmV0dXJuIGdldHRlcjtcbn07IiwiLy8gZGVmaW5lIGdldHRlciBmdW5jdGlvbnMgZm9yIGhhcm1vbnkgZXhwb3J0c1xuX193ZWJwYWNrX3JlcXVpcmVfXy5kID0gZnVuY3Rpb24oZXhwb3J0cywgZGVmaW5pdGlvbikge1xuXHRmb3IodmFyIGtleSBpbiBkZWZpbml0aW9uKSB7XG5cdFx0aWYoX193ZWJwYWNrX3JlcXVpcmVfXy5vKGRlZmluaXRpb24sIGtleSkgJiYgIV9fd2VicGFja19yZXF1aXJlX18ubyhleHBvcnRzLCBrZXkpKSB7XG5cdFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywga2V5LCB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZGVmaW5pdGlvbltrZXldIH0pO1xuXHRcdH1cblx0fVxufTsiLCJfX3dlYnBhY2tfcmVxdWlyZV9fLm8gPSBmdW5jdGlvbihvYmosIHByb3ApIHsgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIHByb3ApOyB9IiwiLy8gZGVmaW5lIF9fZXNNb2R1bGUgb24gZXhwb3J0c1xuX193ZWJwYWNrX3JlcXVpcmVfXy5yID0gZnVuY3Rpb24oZXhwb3J0cykge1xuXHRpZih0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wudG9TdHJpbmdUYWcpIHtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgU3ltYm9sLnRvU3RyaW5nVGFnLCB7IHZhbHVlOiAnTW9kdWxlJyB9KTtcblx0fVxuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xufTsiLCJpbXBvcnQgeyBtZXNzYWdlIH0gZnJvbSAnLi9qcy9tYXRoLmpzJztcclxuaW1wb3J0ICcuL2pzL2NvbXBvbmVudC5qcydcclxuY29uc29sZS5sb2cobWVzc2FnZSk7Il0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9
….这老长。
cheap-source-map
会生成sourcemap,但是会更加高效一些(cheap低开销)
因为它没有生成列映射(Column Mapping)
因为在开发中,我们只需要行信息通常就可以定位到错误了

cheap-module-source-map
会生成sourcemap,类似于cheap-source-map,但是对源自loader的sourcemap处理会更好
这里有一个很模糊的概念:对源自loader的sourcemap处理会更好,官方也没有给出很好的解释
其实是如果loader对我们的源码进行了特殊的处理,比如babel,代码不贴了,看下cheap-source-map 和cheap-module-source-map生成文件的区别:

可以看出,cheap-module-source-map生成的文件更贴近我们的源代码。
hidden-source-map
会生成sourcemap,但是不会对source-map文件进行引用
相当于删除了打包文件中对sourcemap的引用注释
如果我们手动添加进来,那么sourcemap就会生效了
// 被删除掉的
//# sourceMappingURL=bundle.js.map
nosources-source-map
会生成sourcemap,但是生成的sourcemap只有错误信息的提示,不会生成源代码文件;

多个值组合
webpack提供给我们的26个值,是可以进行多组合的。
组合的规则如下:
- inline-|hidden-|eval:三个值时三选一
- nosources:可选值
- cheap可选值,并且可以跟随module的值
那么在开发中,最佳的实践是什么呢?
开发阶段:推荐使用 source-map或者cheap-module-source-map
- 这分别是vue和react使用的值,可以获取调试信息,方便快速开发
测试阶段:推荐使用 source-map或者cheap-module-source-map
- 测试阶段我们也希望在浏览器下看到正确的错误提示
- 发布阶段:false、缺省值(不写)
