当前位置: 首页 > 文档资料 > Node.js 调试指南 >

调试篇 - Source Map

优质
小牛编辑
129浏览
2023-12-01

4.1.1 什么是 Source Map?

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

  1. //@ 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 使用。

4.1.2 uglify-es

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

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

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

  1. $ npm i uglify-es -g
  2. $ npm i source-map-support

创建测试代码:

app.js

  1. require('source-map-support').install()
  2. function sayHello (name) {
  3. throw new Error('error!!!')
  4. console.log(`Hello, ${name}`)
  5. }
  6. sayHello('World')

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

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

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

app.min.js

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

app.min.js.map

  1. {"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 可以显示正确的错误栈:

  1. $ node app.min.js
  2. /Users/nswbmw/Desktop/test/app.js:4
  3. throw new Error('error!!!')
  4. ^
  5. Error: error!!!
  6. at sayHello (/Users/nswbmw/Desktop/test/app.js:4:9)

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

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

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

4.1.3 TypeScript

全局安装 TypeScript:

  1. $ npm i typescript -g

创建测试代码:

app_ts.ts

  1. declare function require(name: string)
  2. require('source-map-support').install()
  3. function sayHello (name: string): any {
  4. throw new Error('error!!!')
  5. }
  6. sayHello('World')

运行:

  1. $ tsc --sourceMap app_ts.ts

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

  1. $ node app_ts.js
  2. /Users/nswbmw/Desktop/test/app_ts.ts:5
  3. throw new Error('error!!!')
  4. ^
  5. Error: error!!!
  6. at sayHello (/Users/nswbmw/Desktop/test/app_ts.ts:5:9)

4.1.4 source-map-support 高级用法

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

  1. require('source-map-support').install({
  2. retrieveSourceMap: function(source) {
  3. if (source === 'compiled.js') {
  4. return {
  5. url: 'original.js',
  6. map: fs.readFileSync('compiled.js.map', 'utf8')
  7. }
  8. }
  9. return null
  10. }
  11. })

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

4.1.5 参考链接

上一节:3.6 Event Loop

下一节:4.2 Chrome DevTools