Source Map的原理探究

摘要: Source Map很神奇,它的原理挺复杂的…

Fundebug经授权转载,版权归原作者所有。

线上产品代码一般是编译过的,前端的编译处理过程包括不限于

  • 转译器/Transpilers (Babel, Traceur)
  • 编译器/Compilers (Closure Compiler, TypeScript, CoffeeScript, Dart)
  • 压缩/Minifiers (UglifyJS)

这里提及的都是可生成Source Map的操作。

经过这一系列骚气的操作后,发布到线上的代码已经面目全非,对带宽友好了,但对开发者调试并不友好。于是就有了Source Map。顾名思义,他是源码的映射,可以将压缩后的代码再对应回未压缩的源码。使得我们在调试线上产品时,就好像在调试开发环境的代码。

来看一个工作的示例

准备两个测试文件,一个 log.js 里包含一个输出内容到控制台的函数:

function sayHello(name) {
if (name.length > 2) {
name = name.substr(0, 1) + '...'
}
console.log('hello,', name)
}

一个main.js 文件里面对这个方法进行了调用:

sayHello('世界')
sayHello('第三世界的人们')

我们使用 uglify-js 将两者合并打包并且压缩。

npm install uglify-js -g
uglifyjs log.js main.js -o output.js --source-map "url='/output.js.map'"

安装并执行后,我们得到了一个输出文件 output.js,同时生成了一个Source Map文件 output.js.map

output.js

function sayHello(name){if(name.length>2){name=name.substr(0,1)+"..."}console.log("hello,",name)}sayHello("世界");sayHello("第三世界的人们");
//# sourceMappingURL=/output.js.map

output.js.map

{"version":3,"sources":["log.js","main.js"],"names":["sayHello","name","length","substr","console","log"],"mappings":"AAAA,SAASA,SAASC,MACd,GAAIA,KAAKC,OAAS,EAAG,CACjBD,KAAOA,KAAKE,OAAO,EAAG,GAAK,MAE/BC,QAAQC,IAAI,SAAUJ,MCJ1BD,SAAS,MACTA,SAAS"}

为了能够让Source Map能够被浏览器加载和解析,

  • 再添加一个 index.html 来加载我们生成的这个output.js 文件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset=