摘要: ## 起源 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.js开发环境。Webpack是一个模块打包工具,它能够处理JavaScript、CSS、图片等静态...
这会全局安装`node-inspector`,以便于在任何项目中使用。 接下来,启动`node-inspector`服务。在你的项目根目录下,运行: ```bash node-inspector ``` 这将启动一个Web服务器,提供了一个界面供我们通过浏览器...
调试篇主要介绍了 Node.js 中的调试技术,包括使用 Source Map、Chrome DevTools 和 Visual Studio Code 等来调试和优化代码。Source Map 是一个基于 Node.js 的调试工具,能够将源代码映射到编译后的代码,用于调试...
使用TypeScript开发Node.js程序主要的优势在于它能够提供静态类型检查、易于重构和自动补全等特性,这些在大型项目中尤其重要。TypeScript可以捕捉一些运行时之前难以发现的错误,使得编码更加可靠和安全。此外,...
源映射完全是通用的(不特定于任何一种语言),因此您可以在同一节点进程中使用具有多种可编译为JS语言的源映射。 安装及使用 节点支持 $ npm install source-map-support 可以使用诸如库来生成。 获得有效的源...
Node.js 是一个基于Chrome V8引擎的JavaScript运行环境,它让开发者可以在服务器端使用JavaScript进行编程,极大地扩展了JavaScript的应用范围。"Node.js-devtools-playground" 是一个专为Node.js开发者设计的独立...
在Node.js开发中,源码映射(Source Map)是一项至关重要的技术,它允许我们在编译后的JavaScript代码中追踪到原始的源码位置,这对于调试、代码混淆和优化过程中的问题定位具有极大的帮助。本文将深入探讨`get-...
你提到的“有npm install运行生成的”,意味着你在本地环境中使用了这个命令来构建和打包项目,这通常包括编译源代码、优化资源、合并文件等步骤,最终生成了可部署的dist目录,其中包含了flv.js和flv-min.js这两个...
JavaScript和Node.js是现代Web开发中的核心技术,它们的测试最佳实践对于确保代码的质量、稳定性和可维护性至关重要。本文将深入探讨这两个领域的测试策略、工具和技术,帮助开发者提高测试效率和准确性。 一、...
vscode 报错之 Could not read source map for file... 解决方案
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工作流中,帮助开发者将多个JavaScript或CSS文件合并成一个文件,并且同时生成源映射文件。源映射在现代前端开发中具有重要意义,因为它们允许...
热节点示例使用 webpack 进行非常简单的热模块替换示例... 使用webpack/hot/signal代替轮询向进程发送信号以触发 HMR 为 node.js 启用 SourceMaps 和 source-map-support 处理热更新失败的情况,即由于错误或不接受模块
首先,对于浏览器端的JavaScript,传统的调试方法是在Chrome浏览器中使用开发者工具(DevTools)。具体步骤如下: 1. 打开Chrome开发者工具; 2. 进入到Sources标签页,会看到页面左侧的JS代码目录; 3. 在需要调试...
总结来说,`process.env` 是Node.js中处理环境依赖和配置的关键工具,它允许开发者在多个环境中灵活地调整应用的行为,而无需更改源代码,提高了代码的可复用性和可维护性。理解并合理利用 `process.env`,可以简化...
10. **构建流程**:了解如何将 TypeScript 代码编译为 JavaScript,以及如何处理源码映射(source map),以便在开发过程中调试 TypeScript 代码。 11. **错误处理**:在 Node.js 中,理解和应用适当的错误处理机制...
- **源码映射**:Node-inspector支持source map,这意味着即使你的代码是经过编译或压缩的,也可以在原始源码中进行调试。 **4. 集成IDE与编辑器** 许多现代的IDE和编辑器,如Visual Studio Code、WebStorm等,...
Node.js是基于Chrome V8引擎的JavaScript运行环境,它使得JavaScript可以在服务器端执行,从而打破了JavaScript只能在浏览器中运行的限制。然而,Node.js并不支持所有的ES6+特性,这就需要Babel在Node.js环境中进行...
var getSourceMapConsumer = require ( 'get-source-map-consumer' ) ; getSourceMapConsumer ( 'http://www.mysite.com/scripts/script.min.js' , function ( error , sourceMapConsumer ) { if ( ! error ) { /...
1. **CommonJS模块化**:这种模块化方式主要在Node.js环境中使用,通过`require`导入模块,`module.exports`或`exports`导出模块。其特点是同步加载,适用于服务器端环境,因为服务器端文件系统读取较快,不关心执行...