Skip to content

Latest commit

 

History

History
162 lines (112 loc) · 4.61 KB

4.1 Source Map.md

File metadata and controls

162 lines (112 loc) · 4.61 KB

Source Map 想必大家并不陌生,在前端开发中通常要压缩 js, css,减少体积,加快网页显示。但带来的后果是如果出现错误,导致无法定位错误,Source Map 应运而生。举个例子, jQuery 1.9 引入了 Source Map,打开 http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js,最后一行是这样的:

//@ sourceMappingURL=jquery.min.map

这就是 Source Map。它是一个独立的 map(其实就是 JSON) 文件,通常与源码在同一个目录下。

Source Map 用在以下几个场景:

  1. 压缩代码,减小体积。比如 jQuery 1.9 的源码,压缩前是 252KB,压缩后是 32KB。
  2. 多个文件合并,减少 HTTP 请求数,针对前端而言。
  3. 其他语言编译成 JavaScript,如:CoffeeScript、TypeScript 等。

本文只讲解如何使用 Source Map,关于 map 文件中字段的含义本文不会解释,有兴趣的请查看参考链接中的文章。接下来我们在 Node.js 环境下以场景 1、3 为例,分别介绍 uglify-es 和 TypeScript 如何结合 Source Map 使用。

uglify-es

uglify-js 是最常用的 js 代码压缩工具,但只支持到 ES5,uglify-es 支持 ES6+ 并且兼容 uglify-js,所以本文使用 uglify-es。

source-map-support 是一个在 Node.js 环境下支持 Source Map 的模块。

安装 uglify-es 和 source-map-support:

$ npm i uglify-es -g
$ npm i source-map-support

创建测试代码:

app.js

require('source-map-support').install()

function sayHello (name) {
  throw new Error('error!!!')
  console.log(`Hello, ${name}`)
}

sayHello('World')

使用 uglify-es 压缩代码文件并生成 map 文件:

$ uglifyjs app.js -o app.min.js --source-map "url=app.min.js.map"

生成 app.min.js 和 app.min.js.map 文件,内容分别如下:

app.min.js

require("source-map-support").install();function sayHello(name){throw new Error("error!!!");console.log(`Hello, ${name}`)}sayHello("World");
//# sourceMappingURL=app.min.js.map

app.min.js.map

{"version":3,"sources":["app.js"],"names":["require","install","sayHello","name","Error","console","log"],"mappings":"AAAAA,QAAQ,sBAAsBC,UAE9B,SAASC,SAAUC,MACjB,MAAM,IAAIC,MAAM,YAChBC,QAAQC,cAAcH,QAGxBD,SAAS"}

此时运行 app.min.js 可以显示正确的错误栈:

$ node app.min.js

/Users/nswbmw/Desktop/test/app.js:4
  throw new Error('error!!!')
        ^
Error: error!!!
    at sayHello (/Users/nswbmw/Desktop/test/app.js:4:9)

如果删除 app.min.js 最后那行注释,重新运行则无法显示正确的错误栈:

$ node app.min.js

/Users/nswbmw/Desktop/test/app.min.js:1
require("source-map-support").install();function sayHello(name){throw new Error("error!!!");console.log(`Hello, ${name}`)}sayHello("World");
                                                                      ^
Error: error!!!
    at sayHello (/Users/nswbmw/Desktop/test/app.min.js:1:71)

source-map-support 是通过 Error.prepareStackTrace 实现的,前面讲解过它的用法,这里不再赘述。

TypeScript

全局安装 TypeScript:

$ npm i typescript -g

创建测试代码:

app_ts.ts

declare function require(name: string)
require('source-map-support').install()

function sayHello (name: string): any {
  throw new Error('error!!!')
}

sayHello('World')

运行:

$ tsc --sourceMap app_ts.ts

生成 app_ts.js 和 app_ts.js.map,运行 app_ts.js 如下:

$ node app_ts.js

/Users/nswbmw/Desktop/test/app_ts.ts:5
  throw new Error('error!!!')
        ^
Error: error!!!
    at sayHello (/Users/nswbmw/Desktop/test/app_ts.ts:5:9)

source-map-support 高级用法

我们可以在调用 install 方法时传入一个 retrieveSourceMap 参数,用来自定义处理 Source Map:

require('source-map-support').install({
  retrieveSourceMap: function(source) {
    if (source === 'compiled.js') {
      return {
        url: 'original.js',
        map: fs.readFileSync('compiled.js.map', 'utf8')
      }
    }
    return null
  }
})

比如将所有 map 文件缓存到内存中,而不是磁盘上。

参考链接

上一节:3.6 Event Loop

下一节:4.2 Chrome DevTools