前端异常解析:Source Map

引子

前端异常解析中介绍了异常的解析,这些异常信息上报后,一般也难以直接的看出什么错误源,因为正式的线上环境中,代码往往都经过了压缩混淆,异常的一些信息都是指向压缩文件。这时候可以根据 Source Map 文件追溯源文件的位置。

简介

最初的源映射格式是由 Joseph Schorr 创建,在 Closure Inspector(谷歌的公共工具)中用来开启 JavaScript 源码级别的调试优化。随着使用了源映射的项目规模扩大,格式冗余开始成为一个问题。v2 版本为了减小源映射整体大小,牺牲了一些简单性和灵活性。目前最新的版本是 v3 。更多信息见 Source Map Revision 3

格式

按照约定,源映射文件跟源文件拥有相同的名称,只是后缀为 .map 。比如 page.js 的产生的源映射名称是 page.js.map 。这个约定并不是强制性的。

源映射整个文件是一个 JSON 对象:

{
  "version" : 3,
  "file": "out.js",
  "sourceRoot": "",
  "sources": ["foo.js", "bar.js"],
  "sourcesContent": [null, null],
  "names": ["src", "maps", "are", "fun"],
  "mappings": "A,AAAB;;ABCDE;"
}
  • version :source map 规范版本,必须是一个正整数。
  • file :可选项,转换后产生的源映射文件名。
  • sourceRoot :可选项,资源更路径,在服务器上重新定位源文件和移除 sources 中重复的值有用处。这个值会预先添加到 sources 字段中每一个值。如果是跟源文件相同的路径,则为空。
  • sources :存放 mappings 中使用的源文件。
  • sourcesContent :可选性,存放源内容。列表的顺序跟 sources 字段中顺序一致。如果一些源要按照名称检索,可能会使用 null
  • names :mappings 中使用的一些标识名。
  • mappings :记录了映射信息的字符串。

结合示例看含义就更清晰了:

前端异常解析:Source Map_第1张图片

更多信息见 Source Map Revision 3

使用

从 Chrome 39 开始,开发者工具中 Source Maps 设置项默认是开启的,更加详细的说明见这里

本地开发的时候,类似 Webpack 构建工具都支持生成 Source Map 文件,调试的时候在 Chrome 中就可以在开发者工具 Sources 栏中看到对应源代码位置。

在正式线上环境中,需不需要生成并部署 Source Map 文件,就看各自的考虑,可以参考一下这篇文章 Should I Use Source Maps in Production? 。要说明一下,浏览器默认不会请求这类文件,不用担心带来额外的请求。如果想要方便排查线上的问题,又不想别人查看源码,服务器可以对 Source Map 文件的访问进行限制。

在正式线上环境中,没办法随时能够操作用户的电脑排查问题,出现异常的时候,假设有 Source Map 文件,该如何进行处理?由此有了下面的疑问:

  1. 如何检测是否有对应 Source Map 文件?
  2. 如何获取到 Source Map 文件?
  3. 如何解析 Source Map 文件?

下面针对这三个问题,依次进行解答。

如何检测是否有 Source Map 文件?

如果压缩后同时生成了 Source Map 文件,那么在压缩后代码的最后一行会是这样:

// js 文件最后一行
//# sourceMappingURL=

// css 文件最后一行
/*# sourceMappingURL= */

所以在出现异常时,得到异常所处的文件之后,判断该文件内容中是否有上面的标记,就可以判断是否有 Source Map 文件。source-map-support 中就是这样进行判断。

如何获取到 Source Map 文件?

在第一个问题里面,知道了有 Source Map 文件,同时也就获取了文件所在位置,直接去请求就可以了。在规范中,推荐在响应头部返回 SourceMap 指向关联的 Source Map 文件,在最新 Chrome 中试了下,并不会默认带上的,可能需要自己手动设置。这个是示例页面

如何解析 Source Map 文件?

理解规范里面编码的方式,就可以反向的进行解析。现有 source-map 库提供了解析的功能。这个是示例页面

什么时候

在上面已经知道怎么去使用 source map 文件,那么该什么时候去进行这个过程?上面给出的示例,都是在前端进行处理,实际上服务器端也可以进行处理,这个时候需要考虑的因素有:

  • 是否会造成影响主流程的运行,因为如果放在前端处理,JavaScript 是单线程,可能会产生影响。
  • 是否能接受额外的请求,上面示例中就有请求 source map 文件,其大小一般都比压缩后源文件要大。
  • 是否能接受源码泄漏的风险。

前端异常处理上报,总的来说是为了及时甚至提前发现问题并处理,为用户提供更好的体验,也为改进产品提供数据参考。从这个方便来看,异常处理上报是一个辅助的功能,应该尽量减少占有的资源,所以 source map 的解析建议放到服务器端处理。

参考资料

你可能感兴趣的:(javascript)