SourceMap 使用教程
一、前言
在前端的工作中主要是用来解决以下三个方面出现的 debug 问题:
a. 代码压缩混淆后
b. 利用 sass 、typeScript 等其他语言编译成 css 或 JS 后
c. 利用 webpack 等打包工具进行多文件合并后
上面三种情况,我们在调试时都是没办法像调试源码般轻松,这就需要 SourceMap 帮助我们在控制台中转换成源码,从而进行 debug 。
二、概念
SourceMap 其实就是一个存储源代码与编译代码对应位置映射的信息文件
三、原理
实际上就是一个 JSON 键值对,利用 VLQ编码与特定的规则存储位置信息。
这里面的逻辑有兴趣的可以看看阮老师的这篇文章《 JavaScript Source Map 详解 》
{
version : 3, // Source map的版本
file: "out.js", // 转换后的文件名
sourceRoot : "", // 转换前的文件所在的目录。如果与转换前的文件在同一目录,该项为空
sources: ["foo.js", "bar.js"], // 转换前的文件。该项是一个数组,表示可能存在多个文件合并
names: ["src", "maps", "are", "fun"], // 转换前的所有变量名和属性名
mappings: "AAgBC,SAAQ,CAAEA" // 记录位置信息的字符串
}
其实不用懂原理直接使用就好,毕竟 .map 文件也是工具生成的,不用自己编写。
四、 webpack中的使用
在 webpack 中使用 source map,是通过配置中的 devtool 字段来设置source map类型。
webpakc中的source map关键字
eval:使用eval包裹块代码
source map:产生.map文件
cheap:不包含列信息
inline:将.map作为dataURL嵌入到js文件内部
module:包含loder的sourcemap
webpakc中的source map类型
大概有26种类型,其实就是根据上面关键字的功能进行的排列组合,分别生成不同类型的Source Map,实际应用中可以根据需要进行配置。
开发环境一般推荐:
- eval - 每个模块都使用 eval() 执行,并且都有 //@ sourceURL。此选项会非常快地构建。主要缺点是,由于会映射到转换后的代码,而不是映射到原始代码(没有从 loader 中获取 source map),所以不能正确的显示行数。
- *** eval-source-map - 每个模块使用 eval() 执行,并且 source map 转换为 DataUrl 后添加到 eval() 中。初始化 source map 时比较慢,但是会在重新构建时提供比较快的速度,并且生成实际的文件。行数能够正确映射,因为会映射到原始代码中。它会生成用于开发环境的最佳品质的 source map。
- eval-cheap-source-map - 类似 eval-source-map,每个模块使用 eval() 执行。这是 “cheap(低开销)” 的 source map,因为它没有生成列映射(column mapping),只是映射行数。它会忽略源自 loader 的 source map,并且仅显示转译后的代码,就像 eval devtool。
- eval-cheap-module-source-map - 类似 eval-cheap-source-map,并且,在这种情况下,源自 loader 的 source map 会得到更好的处理结果。然而loader source map 会被简化为每行一个映射(mapping)。
生产环境一般不推荐使用
实战
在webpack配置文件webpack.config.js中设置devtool即可生成Source Map文件:
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
devtool: "source-map"
};