一、前言
本文基于开源项目:
补充扩展讲解,希望能够让读者一文搞懂 source map的机制。
1.1 what & why Source Map?
在日常开发项目过程中,我们编写的源代码会经过编译、封装、压缩等的处理(通俗理解就是输入 => 转换器 => 输出),最后形成产物代码。
接着我们在浏览器看到的就是一大串连在一起的代码。当我们想debug 还是捕获线上的报错,就会很困难,这时候我们需要将产物代码显示回源代码,source map 就是这样的工具。
1.2 source-map 基本原理?
在编译处理的过程中,在生成代码的同时,生成一个代码中被转换的部分与源代码中相应部分的映射关系表(关系表内容由于篇幅有限这里不展开)。有了这样一张完整的映射表,我们就可以通过 Chrome 控制台中的"Enable Javascript source map"(如下图所示)来实现调试时的显示与定位源代码功能。
1.3 source-map 本地环境 与 生产环境关注点?
开发环境中:
我们关注的是项目构建速度快,质量高,以便于提升开发效率,很少会关注生成文件的大小和访问方式。
生产环境:
我们一般关注是否需要提供线上 source map , 以及生成的文件大小和访问方式是否会对页面性能造成影响等,最后才是质量和构建速度。
二、Webpack 中的 source map 预设
在webpack配置中devtool控制是否生成,以及如何生成 source map的。当我们设置devtool: 'none',那么就会关闭source-map。
我从github上找来以下一段代码,我们一一来分析:
var path = require("path"); module.exports = [ "eval", // 打包非常快速,重新构建非常快速 "eval-cheap-source-map", // 打包比较快,重新构建快速 "eval-cheap-module-source-map", "eval-source-map", // 打包慢,重新构建比较快 "cheap-source-map", "cheap-module-source-map", "inline-cheap-source-map", "inline-cheap-module-source-map", "source-map", "inline-source-map", "hidden-source-map", "nosources-source-map" ].map(devtool => ({ mode: "development", entry: { bundle: "coffee-loader!./example.coffee" }, output: { path: path.join(__dirname, "dist"), filename: `./[name]-${devtool}.js` }, devtool, optimization: { runtimeChunk: true } }));
我们来看一张从webpack上找来的一张关于各个预设的情况:
因此一般在开发环境中我们使用EvalSourceMapDevToolPlugin()。代码如下:
webpack.config.js ... //devtool: 'eval-source-map', devtool: false, plugins: [ new webpack.EvalSourceMapDevToolPlugin({ exclude: /node_modules/, filename: '[name].js.map', // 可不写 module: true, columns: false }) ], ...
上面的代码中,我们将 devtool 设为 false,使用EvalSourceMapDevToolPlugin,通过传入 module: true 和 column:false,达到和预设 eval-cheap-module-source-map 一样的质量,同时传入 exclude 参数,排除第三方依赖包的 source map 生成。
保存设定后通过运行可以看到,在文件体积减小(尽管开发环境并不关注文件大小)的同时,再次构建的速度相比上面表格中的速度提升了将近一倍,达到了最快一级。
Webpack 三个source map处理插件介绍:
EvalDevToolModulePlugin
模块代码后添加 sourceURL=webpack:///+ 模块引用路径,不生成 source map 内容,模块产物代码通过 eval() 封装。
EvalSourceMapDevToolPlugin
生成 base64 格式的 source map 并附加在模块代码之后, source map 后添加 sourceURL=webpack:///+ 模块引用路径,不单独生成文件,模块产物代码通过 eval() 封装。
SourceMapDevToolPlugin
生成单独的 .map 文件,模块产物代码不通过 eval 封装。
平时我们如果有仔细留意,sourceURL=webpack:///这几个代码是不是觉得很熟悉。
三、总结
本篇文章只是对source map知识做了一个简单的梳理,对这块感兴趣的伙伴可以到官网学习学习。
这里推荐几个学习source map资源
七个选项源映射介绍: http://cheng.logdown.com/posts/2016/03/25/679045
映射表原理:http://www.qiutianaimeili.com/html/page/2019/05/89jrubx1soc.html
source-map github: https://github.com/webpack/webpack/tree/master/examples/source-map