`
乱蓬头199303
  • 浏览: 81678 次
文章分类
社区版块
存档分类
最新评论

Node.js 中 source map 使用问题总结

阅读更多
摘要: ## 起源 Node 应用功能越来越复杂,很多业务都开始尝试使用 TypeScript 来开发。现在前端写的 JS 大部分是经过编译过程的,浏览器中通过 source map 的使用,可以很好的解决源码和编译运行时代码差异的问题。 那么,在 Node 服务器环境应该如何使用 source map 呢?最近在重新搭建一个完全基于 ts 的 Node 应用,所有的相关流程看起来都挺好的,唯

起源
Node 应用功能越来越复杂,很多业务都开始尝试使用 TypeScript 来开发。现在前端写的 JS 大部分是经过编译过程的,浏览器中通过 source map 的使用,可以很好的解决源码和编译运行时代码差异的问题。

那么,在 Node 服务器环境应该如何使用 source map 呢?最近在重新搭建一个完全基于 ts 的 Node 应用,所有的相关流程看起来都挺好的,唯一的缺陷是报错信息错误信息指向的是 js 文件。我觉得应该探索下如何让 Node 支持 source map 。

原理
对于 Node 而言,服务器 source map 最大的价值在于错误信息有正确的错误堆栈,所以只要我们能够实现自定义错误堆栈信息就可以了。

恰好 v8 引擎有提供一个私有的 (Stack-Trace-API), 这个提供了让开发者自定义错误 stack 信息的能力。具体来说,开发者可以实现 Error 对象的 prepareStackTrace 方法,如果 Error 对象上定义了这个方法,那么每次错误信息都会经过 Error.prepareStackTrace 处理后返回。

Error.prepareStackTrace 方法可以拿到两个参数,错误基本信息和结构化错误堆栈,第二个参数是一个数组,通过这个数组可以拿到错误文件以及位置信息。最后基于这些信息重新返回一个字符串,这样就可以覆盖 Error 对象的 stack 属性了。

基本代码结构如下:

function prepareStackTrace(error, stack) {
  return error + stack.map(function(frame) {
    return '\n    at ' + wrapCallSite(frame);;
  }).join('');
}
Error.prepareStackTrace = prepareStackTrace;
在 wrapCallSite 方法里面可以通过分析源码,找到 sourceMap 然后返回正确的位置信息。

原理很简单,已经有一个 npm 包 source-map-support 封装好了相关功能。

这看起来已经很完美了。source map 读取只在出现错误的时候才执行,所以**这个功能不会有性能问题,在生成环境也可以开启**。

问题
Stack Trace API 看起来很美好,但现实场景总是更加复杂。我在引入 source-map-support 后,运行起来没什么问题,但在跑测试用例的时候,错误堆栈的位置信息完全不对。

这个问题排查了很久,最终定位到在 wrapCallSite 方法中拿到的 frame 对象返回的行号就是错误的,而这个获取行号的方法是 native code ,这个几乎没法调试了。我想,难道是 Node 的问题?要调试到 Node 源码么?

折腾了很久没有什么效果,就在我打算放弃的时候,我换了一个假设,会不会是某个包依赖影响的?然后我尝试依次删除跑用例时 require 的包,终于发现是因为 egg-bin 默认引入的 power-assert 导致的。

问题定位到后,解决就容易了。但解决这个问题得先讲讲 power-assert 是如何实现的。

power-assert 与 sourceMap
power-assert 作为一个断言库,最大的特色在于错误信息的报告是非常友好的,一张图可以很清晰看到区别

img

实现这样炫酷的报告是需要做一些特殊的处理,把测试用例的代码进行一次转换,举个例子

it('foo', function foo() {
  var a = 'foo';
  var b = 'b';
  assert(a === b);
});
经过 espower-source 处理后,变成了这样

it('foo', function foo() {
  var a = 'foo';
  var b = 'b';
  assert(expr(capture(capture(a, '/0/left') === capture(b, '/0/right'), '/0'), {
      content: 'assert(a === b)',
      filepath: 'bizLogger.test.ts',
      line: 107
  }));
})
注:上面的代码不是真实运行的代码,经过一些删减
对于 assert(a === b); 这样一个表达式,会通过 capture 捕获每一个运算过程的位置和值,最终通过 expr 运算。这样经过转换后,代码运行逻辑不变,但是异常发生的时候可以返回 assert 表达式中每一步的返回值。

我所遇到的问题也就是因为 power-assert 对代码进行了转换,最终异常抛出时,真实 js 异常位置信息是转换后的位置,这个位置自然是无法正确定位到源码位置了。
http://click.aliyun.com/m/23751/
分享到:
评论

相关推荐

    Node.js-使用webpack搭建基于typescript的node开发环境template

    在Node.js开发中,使用构建工具能够极大地提升开发效率和代码质量。本教程将深入探讨如何使用Webpack搭建一个基于TypeScript的Node.js开发环境。Webpack是一个模块打包工具,它能够处理JavaScript、CSS、图片等静态...

    使用node-inspector调试Node.js

    这会全局安装`node-inspector`,以便于在任何项目中使用。 接下来,启动`node-inspector`服务。在你的项目根目录下,运行: ```bash node-inspector ``` 这将启动一个Web服务器,提供了一个界面供我们通过浏览器...

    Node.js-调试指南.pdf

    调试篇主要介绍了 Node.js 中的调试技术,包括使用 Source Map、Chrome DevTools 和 Visual Studio Code 等来调试和优化代码。Source Map 是一个基于 Node.js 的调试工具,能够将源代码映射到编译后的代码,用于调试...

    TypeScript开发Node.js程序的方法

    使用TypeScript开发Node.js程序主要的优势在于它能够提供静态类型检查、易于重构和自动补全等特性,这些在大型项目中尤其重要。TypeScript可以捕捉一些运行时之前难以发现的错误,使得编码更加可靠和安全。此外,...

    node-source-map-support:将源映射支持添加到node.js(用于堆栈跟踪)

    源映射完全是通用的(不特定于任何一种语言),因此您可以在同一节点进程中使用具有多种可编译为JS语言的源映射。 安装及使用 节点支持 $ npm install source-map-support 可以使用诸如库来生成。 获得有效的源...

    Node.js-devtools-playground用于原型设计与调试的独立Devtools

    Node.js 是一个基于Chrome V8引擎的JavaScript运行环境,它让开发者可以在服务器端使用JavaScript进行编程,极大地扩展了JavaScript的应用范围。"Node.js-devtools-playground" 是一个专为Node.js开发者设计的独立...

    node-get-source-map-consumer-源码.rar

    在Node.js开发中,源码映射(Source Map)是一项至关重要的技术,它允许我们在编译后的JavaScript代码中追踪到原始的源码位置,这对于调试、代码混淆和优化过程中的问题定位具有极大的帮助。本文将深入探讨`get-...

    flv.js 和flv-min.js

    你提到的“有npm install运行生成的”,意味着你在本地环境中使用了这个命令来构建和打包项目,这通常包括编译源代码、优化资源、合并文件等步骤,最终生成了可部署的dist目录,其中包含了flv.js和flv-min.js这两个...

    全面详尽的JavaScript和Node.js测试最佳实践(2023年7月).zip

    JavaScript和Node.js是现代Web开发中的核心技术,它们的测试最佳实践对于确保代码的质量、稳定性和可维护性至关重要。本文将深入探讨这两个领域的测试策略、工具和技术,帮助开发者提高测试效率和准确性。 一、...

    vscode 报错之 Could not read source map for file... 解决方案

    vscode 报错之 Could not read source map for file... 解决方案

    Express in Action: Writing, building, and testing Node.js applications

    Evan Hahn is an active member of the Node and Express community and contributes to many open source JavaScript projects. Table of Contents PART 1 INTRO What is Express? The basics of Node.js ...

    前端开源库-gulp-concat-sourcemap

    `gulp-concat-sourcemap`是一个非常实用的前端开源库,它主要用于Gulp工作流中,帮助开发者将多个JavaScript或CSS文件合并成一个文件,并且同时生成源映射文件。源映射在现代前端开发中具有重要意义,因为它们允许...

    hot-node-example:node.js 进程中的 HMR 示例

    热节点示例使用 webpack 进行非常简单的热模块替换示例... 使用webpack/hot/signal代替轮询向进程发送信号以触发 HMR 为 node.js 启用 SourceMaps 和 source-map-support 处理热更新失败的情况,即由于错误或不接受模块

    详解如何在vscode里面调试js和node.js的方法步骤

    首先,对于浏览器端的JavaScript,传统的调试方法是在Chrome浏览器中使用开发者工具(DevTools)。具体步骤如下: 1. 打开Chrome开发者工具; 2. 进入到Sources标签页,会看到页面左侧的JS代码目录; 3. 在需要调试...

    Node.js中环境变量process.env的一些事详解

    总结来说,`process.env` 是Node.js中处理环境依赖和配置的关键工具,它允许开发者在多个环境中灵活地调整应用的行为,而无需更改源代码,提高了代码的可复用性和可维护性。理解并合理利用 `process.env`,可以简化...

    Typescript-Node-Starter:用Typescript编写的Node.js入门包

    10. **构建流程**:了解如何将 TypeScript 代码编译为 JavaScript,以及如何处理源码映射(source map),以便在开发过程中调试 TypeScript 代码。 11. **错误处理**:在 Node.js 中,理解和应用适当的错误处理机制...

    node-inspector

    - **源码映射**:Node-inspector支持source map,这意味着即使你的代码是经过编译或压缩的,也可以在原始源码中进行调试。 **4. 集成IDE与编辑器** 许多现代的IDE和编辑器,如Visual Studio Code、WebStorm等,...

    前端开源库-babel-node-debug.zip

    Node.js是基于Chrome V8引擎的JavaScript运行环境,它使得JavaScript可以在服务器端执行,从而打破了JavaScript只能在浏览器中运行的限制。然而,Node.js并不支持所有的ES6+特性,这就需要Babel在Node.js环境中进行...

    node-get-source-map-consumer:获取 SourceMapConsumer 的实例,当 sourcemap 可用时,对于给定的脚本

    var getSourceMapConsumer = require ( 'get-source-map-consumer' ) ; getSourceMapConsumer ( 'http://www.mysite.com/scripts/script.min.js' , function ( error , sourceMapConsumer ) { if ( ! error ) { /...

    WM_04_模块化原理和source-map1

    1. **CommonJS模块化**:这种模块化方式主要在Node.js环境中使用,通过`require`导入模块,`module.exports`或`exports`导出模块。其特点是同步加载,适用于服务器端环境,因为服务器端文件系统读取较快,不关心执行...

Global site tag (gtag.js) - Google Analytics