You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
TypeError: Cannot read property 'flow_id' of undefined
at render (http://x.y.z.com/index.min.js:1:12314)
at http://x.y.z.com/main_dep.8cba5f027cf7.min.js:1:135578
at http://x.y.z.com/vendors/alpha.850360b98988406d8c20.min.js:119:45314
背景
前端项目发布到生产环境的最终代码一般是后缀为
*.min.js
的文件,这是对源码进行了一系列的转换(如babel)、压缩和混淆操作后的产物,经过这些步骤后的*.min.js
代码具兼容性更好、体积更小、源码更安全的优点,但同时也导致阅读和调试目标代码更加困难了。常见的场景之一是,生产环境上报了一个 JS 异常错误,除了从错误消息中可以获取到部分有用信息外(有时可能完全没用),无法从堆栈报错文件位置中获取有用的信息。
下面是一个JS异常错误:
文件 index.min.js 的第1行的第12314列的附近代码:
从上面堆栈信息中离报错地方最近的位置(index.min.js:1:12314),可以看到这个位置只有一行,明显已经被压缩成了一行,通过代码格式化工具美化后会好一些,但是其中的变量名均已被混淆,依然难以阅读,更糟糕的是像babel/webpack这类工具会插入一些额外代码到最终生成的代码,这些导致难以从目标代码报错位置中解读对应源代码的信息。
从上面的堆栈信息中我们已经知道了报错的是哪个文件,以及所在文件的行号和列号,现在缺的是如何根据这些信息映射回源码中?如果能完成这一步,就可以成功定位线上问题在源码中的准确位置,进而快速分析和修复问题。
sourcemap
早期编写 Web JS 代码是没有转换、压缩和混淆这些步骤的,源码即使最终生产环境部署的代码(知道现在依然有很多站点是这样的),所以不存在上面提到的映射问题。随着前端工程化的发展,各种工具被使用,我们编写的代码与最终部署到生产环境的目标代码已经天差地别了,为了解决目标代码映射回源码的问题,诞生了 sourcemap 技术,其与目标代码一起生成,记录了目标代码中每个字符在源码中的原始位置,有了它可以将目标文件映射回源文件。
下面是 sourcemap 的例子,其中的
*.min.js
是目标代码,*.min.js.map
是对应的 source-map 文件(约定的命名规则是在目标文件后面加上.map
)。sourcemap 文件打开是 JSON 格式,其字段说明如下:
要实现利用 sourcemap 将目标文件位置信息映射回源码文件,需要掌握 sourcemap 的编码规则和计算方式,幸运的是已经有现成的 mozilla/source-map 库可以方便地完成映射过程。
示例
下面是使用 nodejs 编写的工具脚本,它从命令行接收目标文件报错的位置信息(文件名、行号、列号),并输出对应的源文件的文件路径、行号、列号和该位置的符号名称。
脚本 sourcemap.js
测试脚本
小结
随着前端使用的工具越来越多,源代码和目标代码已天差地别,导致目标代码报错时难以关联源代码进行分析,幸运的是 sourcemap 技术弥补了其中的鸿沟,实现了目标代码到源代码的逆向映射。sourcemap 技术不仅用于 JS 代码,理论上可以应用于任意文本之间的映射,例如 css 代码到 less/sass 等逆向映射。本文最后的小工具可以实现快速定位线上目标代码报错,不过更好的方式是将 sourcemap 融入前端工程化体系,构建时自动生成、上传、存储,当生产环境目标代码报错时实时映射成对应版本的源代码。
如果对 sourcemap 的格式和转换原理感兴趣,可进一步阅读:
The text was updated successfully, but these errors were encountered: