阅读目录

一:什么是SourceMap?

二:理解webpack中的SourceMap的eval,inline,sourceMap,cheap,module

三:开发环境和线上环境如何选择sourceMap?

一:什么是SourceMap?

我们在项目进行打包后,会将开发中的多个文件代码打包到一个文件中,并且经过压缩,去掉多余的空格,且babel编译化后,最终会用于线上环境,那么这样处理后的代码和源代码会有很大的差别,当有bug的时候,我们只能定位到压缩处理后的代码位置,无法定位到开发环境中的代码,对于开发不好调式,因此sourceMap出现了,它就是为了解决不好调式代码问题的。官网devtool https://webpack.docschina.org/configuration/devtool/

在讲解之前,我们首先看下项目中的目录结构如下:

  1. ### 目录结构如下:
  2. demo1 # 工程名
  3. | |--- dist # 打包后生成的目录文件
  4. | |--- node_modules # 所有的依赖包
  5. | |--- js # 存放所有js文件
  6. | | |-- demo1.js
  7. | | |-- main.js # js入口文件
  8. | |
  9. | |--- webpack.config.js # webpack配置文件
  10. | |--- index.html # html文件
  11. | |--- styles # 存放所有的css样式文件
  12. | |--- .gitignore
  13. | |--- README.md
  14. | |--- package.json
  15. | |--- .babelrc # babel转码文件

main.js 代码如下:

  1. import demo1Func from './demo1.js';
  2.  
  3. console.log('main.js');

demo1.js 代码如下:

  1. export default function printMe() {
  2. console.log('11111111');
  3. }

webpack.config.js 代码配置如下:

  1. const path = require('path');
  2. // 提取css的插件
  3. const ExtractTextPlugin = require('extract-text-webpack-plugin');
  4. const ClearWebpackPlugin = require('clean-webpack-plugin');
  5.  
  6. module.exports = {
  7. entry: './js/main.js',
  8. output: {
  9. filename: 'bundle.js',
  10. // 将输出的文件都放在dist目录下
  11. path: path.resolve(__dirname, 'dist'),
  12. publicPath: '/dist'
  13. },
  14. mode: 'development',
  15. module: {
  16. rules: [
  17. {
  18. // 使用正则去匹配要用该loader转换的css文件
  19. test: /\.css$/,
  20. loaders: ExtractTextPlugin.extract({
  21. // 转换 .css文件需要使用的Loader
  22. use: ['css-loader']
  23. })
  24. },
  25. {
  26. test: /\.(png|jpg)$/,
  27. loader: 'url-loader',
  28. options: {
  29. limit: 10000,
  30. name: '[name].[ext]'
  31. }
  32. },
  33. {
  34. test: /\.js$/,
  35. exclude: /(node_modules)/, // 排除文件
  36. loader: 'babel-loader'
  37. }
  38. ]
  39. },
  40. resolve: {
  41. // modules: ['plugin', 'js']
  42. },
  43. externals: {
  44. jquery: 'jQuery'
  45. },
  46. devtool: 'eval',
  47. devServer: {
  48. // contentBase: path.join(__dirname, "dist"),
  49. port: 8081,
  50. host: '0.0.0.0',
  51. headers: {
  52. 'X-foo': '112233'
  53. },
  54. // hot: true,
  55. inline: true,
  56. open: true,
  57. overlay: true,
  58. stats: 'errors-only'
  59. },
  60. plugins: [
  61. // new ClearWebpackPlugin(['dist']),
  62. new ExtractTextPlugin({
  63. // 从js文件中提取出来的 .css文件的名称
  64. filename: `main.css`
  65. })
  66. ]
  67. };

基本结构如上,现在我们可以来理解 webpack中的SourceMap的几种常见方式了。

二:理解webpack中的SourceMap的配置项

2.1. eval
  eval 会将每一个module模块,执行eval,执行后不会生成sourcemap文件,仅仅是在每一个模块后,增加sourceURL来关联模块处理前后对应的关系。在webpack中配置devtool: 'eval', 如下打包后的代码:

  1. (function(modules) { // webpackBootstrap
  2. "use strict";
  3. 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?");
  4.  
  5. /***/ "./js/main.js":
  6. /*!********************!*\
  7. !*** ./js/main.js ***!
  8. \********************/
  9. /*! no exports provided */
  10. /***/
  11. (function(module, __webpack_exports__, __webpack_require__) {
  12. "use strict";
  13. 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?");
  14. })
  15. })

如上打包后的代码,每一个打包后的模块后面都增加了包含sourceURL的注释,sourceURL的值是压缩前存放的代码的位置,这样就通过sourceURL关联了压缩前后的代码。并没有为每一个模块生成相对应的sourcemap。

优点是:打包速度非常快,因为不需要生成sourcemap文件。
缺点是:由于会映射到转换后的代码,而不是映射到原始代码,所以不能正确的显示行数。

2.2 source-map

在webpack中配置加上 devtool: 'source-map' 配置完成后,source-map会为每一个打包后的模块生成独立的sourcemap文件,比如在package.json文件中 这样配置:

  1. "scripts": {
  2. "build": "webpack --progress --colors --devtool source-map"
  3. }

然后运行 npm run build 后,会在dist目录下生产map文件。我们继续打包后的代码如下:

  1. (function(module, __webpack_exports__, __webpack_require__) {
  2.  
  3. "use strict";
  4. __webpack_require__.r(__webpack_exports__);
  5. /* harmony import */ var _demo1_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./demo1.js */ "./js/demo1.js");
  6. __webpack_require__(/*! ../styles/main.css */ "./styles/main.css");
  7. console.log('main.js');
  8. /***/ }),
  9.  
  10. /***/ "./styles/main.css":
  11. /*!*************************!*\
  12. !*** ./styles/main.css ***!
  13. \*************************/
  14. /*! no static exports found */
  15. /***/ (function(module, exports) {
  16.  
  17. // removed by extract-text-webpack-plugin
  18.  
  19. /***/ })
  20.  
  21. /******/ });
  22. //# sourceMappingURL=bundle.js.map

如上打包后的代码最后面一句代码是 //# sourceMappingURL=bundle.js.map ,同时在dist目录下会针对每一个模块生成响应的 .map文件,
比如我们在dist目录中会生成 bundle.js.map文件,我们可以打开看下这个文件代码会如下:

  1. {
  2. "version":3,
  3. "sources":[
  4. "webpack:///webpack/bootstrap","webpack:///./js/demo1.js",
  5. "webpack:///./js/main.js","webpack:///./styles/main.css"
  6. ],
  7. "names":["printMe","console","log","require"],
  8. "mappings":";AAAA;AACA;;AAEA;AACA...",
  9. "file":"bundle.js",
  10. "sourcesContent":[],
  11. "sourceRoot": ""
  12. }

上面生成后的map文件是一个javascript对象,可以被解析器读取,它主要有以下几个属性:

version: Source Map 的版本,目前为3.
sources: 转换前的文件,该项是一个数组,表示可能存在多个文件合并.
names: 转换前的所有变量名和属性名。
mappings: 记录位置信息的字符串。
sourcesContent: 转换前的文件内容列表,与sources列表依次对应。
sourceRoot: 转换前的文件所在的目录,如果与转换前的文件在同一个目录,该项为空。

chrome和firefox如何使用Source Map呢?

1. 开启开发者工具

使用快捷键 option + command + i; 或者在 菜单栏选择视图 -> 开发者 -> 开发者工具。

2. 打开设置

点击右上角的三个点的图标,选择Settings, 如下图所示:

3. 开启Source Map
在Sources中,选中 Enable Javascript source maps 如下图所示

开启完成后,我们在 package.json 配置如下代码:

  1. scripts: {
  2. "dev": "webpack-dev-server --progress --colors --devtool source-map --hot --inline",
  3. }

然后在main.js 代码中,添加如下代码:

  1. require('../styles/main.css');
  2. import demo1Func from './demo1.js';
  3.  
  4. console.log('main.js');
  5. console.log(a)

如上a未定义,直接打印a,肯定会报错的。我们在命令行中 运行 npm run dev 后,打开页面会发现报错,报错如下:

然后我们点击 main.js:5 后,会进入main.js代码内,如下图:

2.3 inline(比如 inline-source-map)
该属性不会生成独立的 .map文件,而是将 .map文件以dataURL的形式插入。

如下代码:

  1. /***/ (function(module, __webpack_exports__, __webpack_require__) {
  2.  
  3. "use strict";
  4. __webpack_require__.r(__webpack_exports__);
  5. /* harmony import */ var _demo1_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./demo1.js */ "./js/demo1.js");
  6. __webpack_require__(/*! ../styles/main.css */ "./styles/main.css");
  7.  
  8. console.log('main.js');
  9. console.log(a);
  10.  
  11. /***/ }),
  12.  
  13. /***/ "./styles/main.css":
  14. /*!*************************!*\
  15. !*** ./styles/main.css ***!
  16. \*************************/
  17. /*! no static exports found */
  18. /***/ (function(module, exports) {
  19.  
  20. // removed by extract-text-webpack-plugin
  21.  
  22. /***/ })
  23.  
  24. /******/ });
  25. //# 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的代码如下:

  1. "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, 因为它会增加文件的大小,但是在开发环境中,可以试用下,因为他们打包的速度很快。

因此我们可以总结如下:

在开发环境中我们可以使用 

  1. module.exports = {
  2. devtool: 'cheap-module-eval-source-map'
  3. }

在正式环境中我们可以使用  

  1. module.exports = {
  2. devtool: 'cheap-module-source-map';
  3. }

如上是总结的在开发环境和正式环境使用的sourcemap进行打包的简单思路。

深入浅出的webpack构建工具---devTool中SourceMap模式详解(四)的更多相关文章

  1. 深入浅出的webpack构建工具---webpack3版本的CommonsChunkPlugin详解(六)

    阅读目录 一:什么是CommonsChunkPlugin, 它的作用是什么? 二:webpack3中CommonsChunkPlugin配置项及含义? 回到顶部 一:什么是CommonsChunkPl ...

  2. 深入浅出的webpack构建工具--webpack4+vue+router项目架构(十四)

    阅读目录 一:vue-router是什么? 二:vue-router的实现原理 三:vue-router使用及代码配置 四:理解vue设置路由导航的两种方法. 五:理解动态路由和命名视图 六:理解嵌套 ...

  3. 深入浅出的webpack构建工具---DevServer配置项(二)

    深入浅出的webpack构建工具---DevServer配置项(二) 阅读目录 DevServer配置项 1. contentBase 2. port 3. host 4. headers 5. hi ...

  4. 深入浅出的webpack构建工具---webpack基本配置(一)

    深入浅出的webpack构建工具---webpack基本配置(一) 阅读目录 一:webpack入门构建: 1. 安装webpack到全局 2. 安装webpack到本项目. 3. 如何使用webpa ...

  5. 深入浅出的webpack构建工具--webpack4+vue搭建环境 (十三)

    深入浅出的webpack构建工具--webpack4+vue搭建环境 (十三) 从上面一系列的webpack配置的学习,我们现在来使用webpack来搭建vue的开发环境.首先我们来设想下我们的项目的 ...

  6. 深入浅出的webpack构建工具---AutoDllPlugin插件(八)

    深入浅出的webpack构建工具---AutoDllPlugin插件(八) DllPlugin插件能够快速打包,能把第三方依赖的文件能提前进行预编译打包到一个文件里面去.提高了构建速度.因为很多第三方 ...

  7. 深入浅出的webpack构建工具---PostCss(五)

    一:PostCss是什么?  PostCss是一个样式处理工具,它通过自定义的插件和工具生态体系来重新定义css.它鼓励开发者使用规范的css原生语法编写代码,然后配置编译器转换需要兼容的浏览器版本, ...

  8. 深入浅出的webpack构建工具---HappyPack优化构建(九)

    阅读目录 一:什么是HappyPack? 作用是什么? 二:如何在配置中使用HappyPack? 回到顶部 一:什么是HappyPack? 作用是什么? Webpack是允许在NodeJS中的,它是单 ...

  9. 深入浅出的webpack构建工具---DllPlugin DllReferencePlugin提高构建速度(七)

    阅读目录 一:什么是DllPlugin 和 DllReferencePlugin?作用是什么? 二:在项目中如何使用 DllPlugin 和 DllReferencePlugin? 三:DllPlug ...

随机推荐

  1. Java 面向对象编程小练习(曾经)

    最近打算将之前学习过的小练习分享出来,算是巩固知识.虽然是小练习,但是越看越觉得有趣,温故而知新. 练习:功能跳水比赛,8个评委评分.运动员成绩去掉最高和最低之后的平均分 代码实例: 1.导包 imp ...

  2. Hibernate小解惑.

      1.什么是SessionFactory?什么是Session?httpsession和hibernate的session的有什么区别?     SessionFactory接口负责初始化Hiber ...

  3. 关于IOS下click事件委托失效的解决方案

    一.由于某些特殊情况下,需要用到事件委托,比如给动态创建的DOM绑定click事件,这里就需要事件委托(这里就牵扯到:目标元素和代理元素)目标元素:动态创建的元素,最终click事件需要绑定到该元素 ...

  4. lfs(systemd版本)学习笔记-第1页

    我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! 一名linux爱好者,记录构建Linux From Scratch的过程 经博客园-骏马金龙前辈介绍,开始接触学习lfs,用博客 ...

  5. webpack单独打包一个less文件

    需要将btn.less文件用webpack打包后,放到项目中.在网上百度了各种,遇到了很多问题,现在我将整个步骤整理如下: 1.建一个空的文件夹,命名为init_webpack,在该文件夹下运行: 这 ...

  6. .Net Core(一)环境搭建与基本使用

    .Net Core(一)环境搭建与基本使用 一.系统配置 a) Linux下如果想要打开类似任务管理器,可以使用top命令,在控制台会动态刷新CPU和内存占用.进程等信息.vmstat和free命令可 ...

  7. React.js 新手教程

    正如你能从标题猜到的,这篇文章的目标是给那些有很少编程经验的读者的.比如,像我这样的人:因为迄今为止,我才探索了编程世界6个月.所以,这将是一篇新手村教程! 你只需要拥有对 HTML 和 CSS 的理 ...

  8. centos 7.2 64位 docker安装lamp环境

    1. 删除docker可能有的早期版本 yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docke ...

  9. EasyUI datagrid.getSelections 没有返回正确的选择行数

    Actually i solved the problem. It was because the idField of the table i was using was incorrect. it ...

  10. 使用虚拟环境virtualenv/Virtualenvwrapper隔离多个python

    virtualenv 系统中的多个python混用会导致$PYTHONPATH混乱,或者各个工程对于package的版本要求不同等等情况.有一个简单的解决方案就是用virtualenv来隔离多个pyt ...