如何调试一个Node.js应用程序:提示,技巧和工具
软件开发是复杂的,在某些时候,你的Node.js应用程序会失败。如果你幸运的,您的代码将崩溃,并显示明显的错误消息。如果不走运,应用程序将继续运行,但不会生成您期望的结果。如果您真的很不幸,在第一个用户发现灾难性的磁盘擦除错误之前,一切都可以正常工作。年代trong>
什么是调试?
调试年代trong>是修复软件缺陷的黑魔法。修复一个错误通常很容易——一个修正过的字符或额外的代码行就能解决问题。找到错误是另一回事,开发人员可能会花很多时间试图找到问题的根源。幸运的是,Node.js有一些很好的工具来帮助跟踪错误。
术语
调试有自己的晦涩术语,包括以下内容:
术语 | 解释 |
---|---|
断点 | 调试器停止程序以检查其状态的点 |
调试器 | 提供调试功能的工具,如逐行运行代码以检查内部变量状态 |
功能 | 正如声明中所说:“这不是一个bug,这是一个功能”。所有开发者在他们职业生涯的某个阶段都会这么说 |
频率 | bug发生的频率和条件是什么 |
不管用 | 最常见但最没用的错误报告 |
记录点 | 发送给调试器的一条指令,用于显示执行过程中某个时点上变量的值 |
日志记录 | 将运行时信息输出到控制台或文件 |
逻辑错误 | 程序可以工作,但没有按照预期的方式工作 |
优先级 | 在计划更新列表中分配bug的位置 |
竞态条件 | 难以追踪的bug依赖于不可控事件的顺序或时间 |
重构 | 重写代码以提高可读性和维护 |
回归 | 以前修复的错误可能由于其他更新而重新出现 |
相关的 | 与另一种昆虫相似或相关的昆虫 |
繁殖 | 导致错误所需的步骤 |
RTFM错误 | 用户不称职伪装成错误报告,通常后面跟着一个响应“Read The翻转手册》 |
进入 | 在调试器中逐行运行代码时,进入被调用的函数 |
走出 | 逐行运行时,完成当前函数的执行并返回调用代码 |
跨过 | 逐行运行时,完成命令的执行,而不进入它调用的函数 |
严重程度 | bug对系统的影响。例如,数据丢失通常被认为比UI问题更有问题,除非发生的频率非常低 |
堆栈跟踪 | 错误发生前调用的所有函数的历史列表 |
语法错误 | 印刷错误,例如console.lug () |
用户错误 | 由用户而不是应用程序引起的错误,但仍然可能导致更新,这取决于该人的资历 |
看 | 要在调试器执行期间检查的变量 |
监视点 | 与断点类似,不同的是,当变量被设置为特定值时,程序将停止 |
如何避免bug
在测试应用程序之前,通常可以防止出现错误。
使用好的代码编辑器
一个好的代码编辑器将提供许多功能,包括行号、自动补全、颜色编码、括号匹配、格式化、自动缩进、变量重命名、代码段重用、对象检查、函数导航、参数提示、重构、不可达代码检测、建议、类型检查等等。
Node.js开发人员被免费的编辑器宠坏了,比如VS代码,原子,括号,以及大量的商业替代品。
使用代码检查器
在保存和测试代码之前,linter可以报告代码错误,例如语法错误、糟糕的缩进、未声明的变量和不匹配的括号。JavaScript和Node.js的流行选项包括ESLint,JSLint,JSHint.
这些通常被安装为全局Node.js模块,这样你就可以从命令行运行检查:
eslint myfile.js
然而,大多数linter都有代码编辑器插件,例如ESLint for VS Code而且Atom的linter-eslint当你输入时检查你的代码:
使用源代码控制
一个源代码控制系统,如Git可以帮助保护您的代码和管理修订。更容易发现bug是何时何地被引入的,以及谁应该受到责备!在线存储库,例如GitHub而且Bitbucket都提供免费空间和管理工具。
采用问题跟踪系统
如果没有人知道一个漏洞是否存在?问题跟踪系统用于报告错误、查找重复、记录复制步骤、确定严重程度、计算优先级、分配开发人员、记录讨论以及跟踪任何修复的进度。
在线源代码存储库通常提供基本的问题跟踪,但是专用的解决方案可能适用于较大的团队和项目。
使用测试驱动开发
测试驱动开发(TDD)是一种开发过程,它鼓励开发人员在编写函数之前编写测试函数操作的代码,例如,当函数Y被传递输入Z时是否返回X.
可以在开发代码时运行测试,以证明函数可以工作,并在进行进一步更改时发现任何问题。也就是说,你的测试也可能有bug…
一步
人们很容易熬夜,徒劳地试图找到一个讨厌的bug的源头。不喜欢。走开,做点别的事。你的大脑会下意识地解决问题,并在凌晨4点把你叫醒。即使这种情况没有发生,新鲜的眼睛也会发现明显缺失的分号。
Node.js调试:环境变量
环境变量可用于控制Node.js应用程序设置。最常见的是NODE_ENV
,通常设置为发展
当调试。
Linux/macOS下支持设置环境变量:
NODE_ENV年代pan>=年代pan>发展
窗户cmd
:
集年代pan>NODE_ENV年代pan>=年代pan>发展
或者Windows Powershell:
env美元年代pan>: NODE_ENV<年代pan class="token operator">=年代pan>“发展”年代pan>
在内部,应用程序将启用进一步的调试特性和消息。例如:
// NODE_ENV设置为“development”?年代pan>常量年代pan>DEVMODE年代pan>=年代pan>(年代pan>过程<年代pan class="token punctuation">.年代pan>env年代pan>.年代pan>NODE_ENV年代pan>= = =年代pan>“发展”年代pan>)年代pan>;年代pan>如果年代pan>(年代pan>DEVMODE年代pan>)年代pan>{年代pan>控制台年代pan>.年代pan>日志年代pan>(年代pan>应用程序以开发模式在端口${port}上启动年代pan>)年代pan>;年代pan>}年代pan>
NODE_DEBUG
使用Node.js启用调试消息util.debuglog
(见下文),但也可以参考您的主要模块和框架的文档,以发现更多的选项。
注意,环境变量也可以保存到.env
文件。例如:
NODE_ENV=development NODE_LOG=./log/debug.log SERVER_PORT=3000 DB_HOST=localhost DB_NAME=mydatabase .log
然后使用dotenv
模块:
需要年代pan>(年代pan>“dotenv”年代pan>)年代pan>.年代pan>配置年代pan>(年代pan>)年代pan>;年代pan>
Node.js调试:命令行选项
各种各样的命令行选项可以传递给节点
运行时启动应用程序。其中最有用的是——trace-warnings
,它为进程警告(包括弃用)输出堆栈跟踪。
可以设置任意数量的选项,包括:
——enable-source-maps
:启用源映射(实验性)——throw-deprecation
:当使用已弃用的特性时抛出错误——检查
:激活V8检查器(见下文)
作为一个例子,让我们尝试记录日志加密模块DEFAULT_ENCODING
财产,在Node v10中已弃用:
常量年代pan>加密<年代pan class="token operator">=年代pan>需要年代pan>(年代pan>“密码”年代pan>)年代pan>;年代pan>函数年代pan>酒吧年代pan>(年代pan>)年代pan>{年代pan>控制台年代pan>.年代pan>日志年代pan>(年代pan>加密<年代pan class="token punctuation">.年代pan>DEFAULT_ENCODING年代pan>)年代pan>;年代pan>}年代pan>函数年代pan>喷火年代pan>(年代pan>)年代pan>{年代pan>酒吧年代pan>(年代pan>)年代pan>;年代pan>}年代pan>喷火年代pan>(年代pan>)年代pan>;年代pan>
现在用以下命令运行它:
节点index.js
然后我们会看到:
buffer (node:7405) [DEP0091] DeprecationWarning: crypto.使用实例DEFAULT_ENCODING已弃用。
然而,我们也可以这样做:
Node——trace-warnings index.js
这会产生以下结果:
buffer (node:7502) [DEP0091] DeprecationWarning: crypto. [DEP0091] DeprecationWarning: crypto.]DEFAULT_ENCODING已弃用。at bar (/home/Desktop/index.js:4:22) at foo (/home/Desktop/index.js:8:3) at Object。<匿名> (/home/Desktop/index.js:11:1)_compile (internal/modules/cjs/loader.js:1151:30) at Object.Module._extensions. js (internal/modules/cjs/loader.js:1171:10) at Module. Module. jsload (internal/modules/cjs/loader.js:1000:32)_load (internal/modules/cjs/loader.js:899:14)executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12) at internal/main/run_main_module.js:17:47
这告诉我们,弃用警告来自第4行代码console.log
语句),当酒吧
函数了。的酒吧
函数调用喷火
函数在第8行和喷火
函数在脚本的第11行被调用。
注意,同样的选项也可以传递给nodemon.
控制台的调试
调试应用程序最简单的方法之一是在执行时将值输出到控制台:
控制台年代pan>.年代pan>日志年代pan>(年代pan>myVariable<年代pan class="token punctuation">)年代pan>;年代pan>
很少有开发人员钻研这个简单的调试命令之外的东西,但是他们错过了更多的可能性,包括:
控制台 方法 |
描述 |
---|---|
. log(味精) |
向控制台输出一条消息 |
.dir (obj,选择) |
使用util.inspect 漂亮地打印对象和属性 |
.table (obj) |
以表格格式输出对象数组 |
. error(味精) |
输出错误消息 |
.count(标签) |
一个已命名的计数器,报告该行已执行的次数 |
.countReset(标签) |
重置一个命名计数器 |
.group(标签) |
缩进一组日志消息 |
.groupEnd(标签) |
结束缩进的组 |
.time(标签) |
启动一个计时器来计算操作的持续时间 |
.timeLog((标签) |
报告计时器启动后经过的时间 |
.timeEnd(标签) |
停止计时器并报告总持续时间 |
.trace () |
输出堆栈跟踪(所有调用函数的列表) |
.clear () |
清除控制台 |
console.log ()
接受逗号分隔值的列表。例如:
让年代pan>x<年代pan class="token operator">=年代pan>123年代pan>;年代pan>控制台年代pan>.年代pan>日志年代pan>(年代pan>“x:“年代pan>,年代pan>x<年代pan class="token punctuation">)年代pan>;年代pan>// x: 123年代pan>
然而,ES6解构可以用更少的输入工作提供类似的输出:
控制台年代pan>.年代pan>日志年代pan>(年代pan>{年代pan>x<年代pan class="token punctuation">}年代pan>)年代pan>;年代pan>// {x: 123}年代pan>
较大的对象可以使用以下命令输出为压缩字符串:
控制台年代pan>.年代pan>日志年代pan>(年代pan>JSON年代pan>.年代pan>stringify年代pan>(年代pan>obj<年代pan class="token punctuation">)年代pan>)年代pan>;年代pan>
util.inspect
将对象格式化为更容易阅读,但是console.dir ()
为你做艰苦的工作。
node . jsutil.debuglog
在node . js跑龙套
模块提供了内置的debuglog
方法,该方法有条件地将消息写入STDERR
:
常量年代pan>跑龙套<年代pan class="token operator">=年代pan>需要年代pan>(年代pan>“跑龙套”年代pan>)年代pan>;年代pan>常量年代pan>debuglog<年代pan class="token operator">=年代pan>跑龙套<年代pan class="token punctuation">.年代pan>debuglog年代pan>(年代pan>“myapp”年代pan>)年代pan>;年代pan>debuglog年代pan>(年代pan>myapp调试信息[%d]年代pan>,年代pan>123年代pan>)年代pan>;年代pan>
当NODE_DEBUG
环境变量设置为myapp
(或通配符,如*
或我*
),消息显示在控制台中:
NODE_DEBUG年代pan>=年代pan>myapp节点索引<年代pan class="token number">9876年代pan>: myapp调试消息<年代pan class="token punctuation">[年代pan>123年代pan>]年代pan>
在这里,9876
是Node.js进程ID。
默认情况下,util.debuglog
是沉默。如果运行上面的脚本而不设置NODE_DEBUG
变量时,将不会向控制台输出任何内容。这允许您在代码中留下有用的调试日志,而不会使控制台变得混乱。
使用日志模块调试
如果您需要更复杂的消息传递级别、详细程度、排序、文件输出、概要分析等选项,则可以使用第三方日志记录模块。常见的选项包括:
Node.js V8检查器
在以下部分中,pagehit项目开发的其他教程用于说明调试概念。你可以用以下方法下载:
git年代pan>克隆https://github.com/site必威西盟体育网页登录point-editors/pagehit-ram
也可以使用自己的代码。
Node.js是V8 JavaScript引擎的包装器,它包含自己的引擎检查器和调试客户端.首先,使用检查
论点(不要与之混淆——检查
)以启动应用程序:
节点inspect ./index.js
调试器将在第一行处暂停并显示调试>
提示:
<年代pan>调试器监听ws://127.0.0.1:9229/6f38abc1-8568-4035-a5d2-dee6cbbf7e44<年代pan class="token operator"><年代pan>如需帮助,请参见:https://nodejs.org/en/docs/inspector<年代pan class="token operator"><年代pan>调试器。启动时中断<年代pan class="token keyword">在年代pan>index.js: 7<年代pan class="token number">5年代pan>常量<年代pan class="token number">6年代pan>//默认HTTP端口<年代pan class="token operator">>年代pan>7年代pan>港口<年代pan class="token operator">=年代pan>3000年代pan>,<年代pan class="token number">8年代pan>9年代pan>// Node.js模块调试<年代pan class="token operator">>年代pan>
你可以输入:
续
或c
:继续执行下一个
或n
:执行下一条命令一步
或年代
:进入一个被调用的函数出
或o
:退出函数并返回调用函数的命令暂停
:暂停运行代码
其他选项包括:
- 查看变量值
手表(“myvar#”)
- 属性设置断点
setBreakpoint ()
/某人()
命令(通常插入一个调试器;
语句) 重新启动
一个脚本.exit
调试器(初始.
是必需的)
如果这听起来非常笨拙,它是.只有在绝对没有其他选择,感觉特别受虐,并且没有使用Windows(这通常是有问题的)时,才使用内置的调试客户端。
使用Chrome调试Node.js
Node.js检查器(没有调试器客户端)是用——检查
国旗:
Node——inspect ./index.js
注意:nodemon
可以用来代替节点
如果有必要的话)。
这将启动调试器监听127.0.0.1:9229
,任何本地调试客户端都可以附加到:
调试器监听ws://127.0.0.1:9229/20ac75ae-90c5-4db6-af6b-d9d74592572f
如果你在其他设备或Docker容器上运行Node.js应用程序,请确保端口9229
是可访问的,并授予远程访问使用:
节点——检查<年代pan class="token operator">=年代pan>0.0年代pan>.0.0:9229。/ index.js
或者,您可以使用——inspect-brk
在第一个语句上设置断点,以便立即暂停应用程序。
打开Chrome浏览器,输入chrome: / /检查
在地址栏。
注意:如果Node.js应用程序不显示为<年代trong>遥远的目标年代trong>,确保<年代trong>发现网络目标年代trong>选中,然后单击<年代trong>配置年代trong>,添加应用程序所在设备的IP地址和端口。
点击目标的<年代trong>检查年代trong>链接来启动DevTools。任何有浏览器调试经验的人都会立即熟悉它。
的<年代trong>+添加文件夹到工作区年代trong>link允许你选择Node.js文件在你的系统中的位置,这样就更容易加载其他模块并进行更改。
单击任何行号设置一个断点,用绿色标记表示,当到达该代码时停止执行:
变量可以添加到<年代trong>看年代trong>面板上的<年代trong>+年代trong>图标,并输入他们的名字。它们的值在执行暂停时显示。
的<年代trong>调用堆栈年代trong>窗格显示了为了到达这一点调用了哪些函数。
的<年代trong>范围年代trong>窗格显示所有可用的本地和全局变量的状态。
的<年代trong>断点年代trong>窗格显示所有断点的列表,并允许启用或禁用它们。
上面的图标<年代trong>调试器停了下来年代trong>消息可用于恢复执行、跨进、跨进、跨出、跨出、禁用所有断点和暂停异常。
用VS Code调试Node.js
当你在本地系统上运行Node.js应用程序时,无需任何配置就可以启动Node.js调试。打开起始文件(通常是index.js
),激活<年代trong>运行和调试年代trong>窗格,并单击<年代trong>运行和调试Node.js (F5)年代trong>按钮。
调试屏幕类似于Chrome DevTools<年代trong>变量年代trong>,<年代trong>看年代trong>,<年代trong>调用堆栈年代trong>,<年代trong>加载脚本年代trong>,<年代trong>断点年代trong>列表。
可以通过单击行号旁边的槽来设置断点。您也可以右键单击。
用这个右键单击,你可以设置如下:
一个标准断点。
条件断点,在满足条件时停止—例如,
数> 3
.一个对数点,有效的
console.log ()
没有代码!任何字符串都可以用花括号表示的表达式输入-例如,{数}
属性的值数
变量。
注:别忘了打返回为VS Code创建条件断点或日志点。
顶部的调试图标栏可用于恢复执行、跳过、进入、退出、重新启动或停止应用程序和调试。相同的选项也可从<年代trong>调试年代trong>菜单上的项目。
有关更多信息,请参阅在Visual Studio代码中调试.
高级调试配置
在调试远程服务或需要使用不同的启动选项时,需要进一步配置。VS Code将启动配置存储在launch.json
在.vscode
项目中的文件夹。要生成或编辑文件,请单击页面右上方的齿轮图标<年代trong>运行和调试年代trong>窗格。
属性中可以添加任意数量的配置设置配置
数组中。单击<年代trong>添加配置年代trong>按钮,选择一个选项。VS Code可以:
- 发射年代trong>一个使用Node.js本身的进程,或者
- 附加年代trong>到Node.js检查器进程,可能运行在远程机器或Docker容器上
在上面的示例中,定义了一个单独的Nodemon启动配置。保存launch.json
中,选择nodemon
的顶部的下拉列表中<年代trong>运行和调试年代trong>窗格,并单击绿色的开始图标。
有关详细信息,请参见启动配置.
其他Node.js调试工具
的Node.js调试指南为其他ide和编辑器提供建议,包括Visual Studio, JetBrains, WebStorm, Gitpod和Eclipse。Atom还有一个node-debug扩展。
ndb提供了一个改进的调试体验具有强大的功能,如附加到子进程和脚本黑盒,因此只显示特定文件夹中的代码。
的IBM report-toolkit for Node.js工作时通过分析数据输出节点
是由——实验报告
选择。
最后,商业服务等LogRocket而且Sentry.io在客户端和服务器中集成您的实时web应用程序,以便在用户遇到错误时记录错误。
得到调试!
Node.js有一系列很棒的调试工具和代码分析器,可以提高应用程序的速度和可靠性。他们是否能引诱你离开console.log ()
那是另一回事!