科普sourcemap v3 proposal

1,119 阅读4分钟
 2020基本上所有的前端项目都迈进了工程化,那么面对错误的监控,源码的定位,就离不开sourcemap的帮助

1.source map

1.1 source map是什么

source map是压缩后的代码映射到源码的文件位置映射文件, 我们见到的source map都基于v3 proposal实现。

1.2 source map的发展史

提起它的出现(v1),是源于google一个js压缩工具Closure Compile,之后为了提供对应源码级调试工具Closure Inspector而发明的。但是v1的sourcemap文件,由于记录了详细的位置信息,生成的map文件是压缩后文件体积的近10倍,随着项目扩大,map文件体积就变成一个棘手的问题。

v2版本,使得map文件的体积减少了50%;v3版本的出现,又使map的体积减少了50%。

而v3的break change是采用了base64 VLQ(Variable Length Quantity)编码。

1.3 source map格式详解

首先看v3的格式source map的格式

{
    version : 3,  // 版本(正整数)
    file: "out.js", // 生成的文件名
    sourceRoot : "", // 文件夹结构预设置源文件(可节省空间的技术)
    sources: ["foo.js", "bar.js"],  // 源文件(合并了多个文件可用数组格式)
    names: ["src", "maps", "are", "fun"], // 包含所有出现在代码中的变量名称或方法
    mappings: "AAgBC,SAAQ,CAAEA",  // 这个mapping是重点,映射法则是提升50%体积大小的核心
}
  • 生成代码的每一行,通过分号(;)区分
  • 每段代码(segment),通过逗号( , )区分
  • segment通常有1或4或5位的可变长度领域,表示该位置对应的转换前的源码位置

1.3.1 segment片段详解

正如我提到的那样,每一段代码由1,4或5位组成,上图是可变长度的四位与一个连续位(g), 我将拆分这个段,然后向你展示 source map如何映射回原始位置。 上图是纯粹基于base64 VLQ编码组成, 想要知道代表什么,还需要经过进一步的处理。

每一个片段的每一位字符分别代表(位数均以0开始做索引):

第一位:生成文件的列数。如果是第一个片段的第一位,或者是生成行的第一位,则这个位置保留基准base64VLQ,否则此字段包含先前出现为基准的base 64VLQ。这个位和下面的位不同,因为其他的位在新行后,都将重置。

第二位:sources属性中对应的文件

如果source属性存在,则该字段一直存在;

如果该字段是在新行中首次出现,则为整个值,否则认为base64VLQ的叠加值。

第三位:源码对应的行数

第四位:源码的列数

第五位:names中的变量(可选)

并不是每一段都有对应的names变量名, 所以的段的长度就是4位或5位,上图的g位就是连续位,这允许Base64和VLQ解码阶段进行进一步优化,连续位是基于一个段的来构建,这样就可以存储一个大数值而不必存储大数值本身,这起源于midi格式,是一种非常聪明的节约空间的技术。

JavaScript是基于32位计算的,1位作为标志位,31位表示数值大小,则能表示的数值范围是[-231..231-1],每一位也有这种限制

上图的AAgBC, 可以看做[A, A, gB, C ], 根据vlq解码最终变成了[0, 0, 16, 1]。


结果验证可点击:murzwin.com/base64vlq.h…

AAgBC → [0, 0, 16, 1] 就表示,生成后文件的第一行(没有分号说明是一行)的第0列,对应source中第0个索引foo.js文件中16行的第1列。

1.4 使用流程

1.首先需要通过工具(webpack, gulp, rollup, closure Compile)生产出source map文件

2.转换后文件加入一个注释,指向source map。注释的语法类似:

javascript 文件

//# sourceMappingURL=http://example.com/path/to/your/sourcemap.map

3.只有当你打开了控制台,浏览器才会帮你下载source map文件,并解析生效。

1.5 实践-webpack

webpack通过devtool来生成source map


详情可点击:webpack.docschina.org/configurati…

简单的来讲:在生产环境用最好不用到sourcemap, 如果要用到,使用cheap-module-source-map.

参考资料:

  1. Introduction to JavaScript Source Maps
  2. Source Map Revision 3 Proposal