天天看点

#yyds干货盘点#都在说sourceMap,今天来聊聊

SourceMap 想必大家都不陌生。线上的代码多是压缩后的,如果线上有报错却只能调试那个代码多半是个噩梦。因此我们需要有一个桥梁帮助我们搭建起源代码及压缩后代码的联系,sourceMap 就是起了这个作用。

SourceMap对现在的项目来说也是比较重要的,因为在打包完成之后的代码是经过​

​混淆​

​、​

​压缩​

​的,不能很好的进行定位。如果想看到准确的代码位置,​

​Source Maps(源映射)​

​ 通过提供原始代码和转换后代码之间的映射 来解决这个问题。

在前端工程体系中,一份代码从开发到上线,大多需要经过打包编译的步骤,分别是:

  1. 将jsx, tsx, ts 之类的文件类型转译成runtime可以识别的js
  2. 将js转译成适用范围更广的es5
  3. 将多个js文件压缩成一个最终的产物,并对代码进行一定程度的混淆

sourcemap原理

sourcemap的构成

为了更清晰的描述sourcemap的生成,我用一个最简单的case来编译并生成sourcemap:

// input 
const example = () => { 
  console.log('example'); 
} 
 
// output 
"use strict"; 
 
var example = function example(){ 
  console.log("example"); 
}; 
复制代码      

利用babel将上述代码转为es5的同时,我们可以得到一份sourcemap:

{ 
  "version": 3, 
  "sources": [ 
    "src/example.js" 
  ], 
  "names": [ 
    "example", 
    "console", 
    "log" 
  ], 
  "mappings": ";;AAAA,IAAMA,OAAO,GAAG,SAAVA,OAAU,GAAM;AACpBC,EAAAA,OAAO,CAACC,GAAR,CAAY,SAAZ;AACD,CAFD", 
  "sourcesContent": [ 
    "const example = () => {\n  console.log(\"example\");\n};\n" 
  ] 
}       

可以看到其有多个属性,分别代表着:

  1. version: source map 的版本号。
  2. sources: 转换前的文件。该项是一个数组,可能存在多个文件合并成一个文件。
  3. names: 转换前的所有变量名和属性名。
  4. mappings: 记录位置信息的字符串。
  5. sourceContent: 原始内容。

其中最重要的,便是记录着原始代码和编译后代码映射关系的mappings字段。

SourceMap的版本

关于sourcemap的版本

  • 2009年,google介绍他的一个编译器​​Cloure Compiler​​时,也顺便推出了一个调试插件Closure Inspector,可以方便调试编译后的代码,这个就是 sourcemap 的雏形
  • 2010年,Closure Compiler Source Map 2.0中,共同制定了一些标准,已决定使用base64编码,但是生成的map文件要比现在大很多
  • 2011年,第三代出炉, ​​Source Map Revision 3 Proposal​​,也就是我们现在用的 sourcemap 的版本,这也就是为什么我们上面map文件的 version=3 了,这一版对算法进行了优化,大大缩小了map文件的体积

第一版生成的map文件大概有转化后文件的10倍大,第二版则将体积减少了20%~30%,第三版又在v2的基础上体积减少了一半