本文的主题:
-
什么是source-map?
-
mappings属性解读
-
如何使用source-map
-
devtool的配置和对应值的含义
什么是source-map
我们知道现在前端是工程化的时代,开发写过代码会经过一些列的操作:
-
转译(babel,把es6/图片/css转成浏览器可以识别的代码)
-
编译器 typescript
-
压缩/Minifiers (UglifyJS)
经过这些操作以后我们的代码已经面目全非,但是我们又需要在开发或者线上的时候定位问题。此时就产生了source-map。souce-map就是生成一些map文件,这些文件能够记录源文件代码具体位置信息(记录的详细程度和配置有关)。
总结:源码映射,可以将编译压缩后的代码再对应回未压缩的源码。
文件解析
生成的source-map生成的是json文件,其中字段有以下几个:
{
"version":3,
"file":"js/nosources-source-map/nosources-source-map.js",
"mappings":"AAAAA,BBBBB;CCCCC",
"sources":[
"webpack://02_webpack_config_start/./src/index.js"
],
"names":[
"console",
"log",
"log1111"
],
"sourceRoot":""
}
version: source-map的版本
file: 生成的map文件路径名称
sources: 源文件
names: 源文件转换的变量名和属性名
mappings:该字段是map文件的关键,存储产出文件files和源文件的对应关系
mappings属性解读
"mappings":"AAAAA,BBBBB;CCCCC"
mappings是记录的核心,这一对字母是什么意思呢?
mappings属性解读分三层属性:
第一层是行对应,以分号(;)隔开,每个分号表示源码的一行。上面表示源代码有2行信息。
第二层是位置对应,以逗号(,)隔开。比如,上面的AAAAA,BBBBB 中AAAA表示第一行的第一个变量或者属性,BBBB表示第一行的第二个变量。
第三层是位置转换,每一个逗号表示一个位置信息,这些信息经过了BASE64 VLQ编码。
读到这里,那么问题又来了,
第一:一个逗号表示一个基本的位置信息的话,存储了哪些位置信息呢?
第二,BASE64 VLQ编码是什么意思?
第一个问题:
记录了5位的信息(00150):
-
第一位,表示在转换后的代码中的第几列。
-
第二位,表示该位置在sources中的哪一个文件,sources中的索引。
-
第三位,表示在转换前文件的第几行
-
第四位,表示在转换前文件的第几列
-
第五位,表示names中的索引。
生成文件的列,源文件的索引,源文件行号,源文件列号,名称的索引
其中,源文件的索引,源文件的列号,名称的索引都是可以省略(devtool的配置不同可以不生成这些信息)。所以这是利用可变长度来表示的原因。
具体位置相关的设计思想参考该文章: Source Map的原理探究 ,这里不做深入探讨。
第二个问题:
VLQ: Variable-length quantity
-
长度可变
-
使用base64编码字符
-
可以精确的表示很大的数值
具体位置转换规则参考这篇文章: JavaScript Source Map 详解 - 阮一峰的网络日志
如何使用source-map
生成source-map: 只需要在webpack中启用devtool功能即可
devtool: 'eval'
具体配置可以参考官网。
基本类型:
eval: 源码会被eval函数包含
source-map: 会生成一个独立的map文件
cheap: 只关心文件的行号,不关心列号
inline: 生成的map数据以dataurl的方式注入到生成的文件中
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoianMvaW5saW5lLXNvdXJjZS1tYXA...
module: 错误能够还原到源文件。
hidden: 不会生成sourceMappingURL 这种映射。可以把source-map文件单独放在其他服务器,比如错误报警器。
tips: http响应头中可以使用source-map
组合类型:
eval: 没有源文件,只能定位行
eval-source-map: 可以映射源文件,并且可以定位行和列
cheap-source-map: 不可以映射源文件,但是只能定位行信息
eval-cheap-source-map: 转换es6以后的文件,不可以映射源文件,但是只能定位行信息
cheap-module-source-map: 可以映射源文件,只能显示行
hidden-source-map: 生成的打包文件中没有引入source-map文件,但是生成了source-map文件。适合第三方库。
nosource-source-map: 生成了map文件,但是看不到源代码,可以看到报错的文件和行列信息
source-map的选择:
开发环境:cheap-module-eval-source-map
隐藏了列信息,同时可以定位到源文件代码文件,同时生成单独的map文件,该文件放到eval中引进去。这种在内存中加载会相对比较快。
生产环境: cheap-module-source-map
只看到源文件的行信息。
注意: 不要不map文件放在公网,这样相当于暴露你的源码在外面了。