本文转载自微信公众号《神光的编程秘籍》,作者神说有光zxg。转载本文请联系神光编程秘籍公众号。学习nodejs最重要的是什么?或许每个人都有自己的答案。我觉得学习nodejs最重要的能力除了掌握基本的api和一些常用的包之外,就是学会调试器的使用。因为当流程比较复杂的时候,断点调试可以帮助你更好的理清逻辑,当有bug的时候,也可以更快的定位问题。狼叔说,会不会用debugger是区分一个程序员nodejs水平的重要标志。本文分享调试器的原理和vscode调试器的使用技巧。debugger原理在运行nodejs代码的时候,如果带上--inspect(可以断点)或者--inspect-brk(可以断点,并且在第一行断)参数,那么就会以debugger模式启动:即可看到那个节点启动了一个websocket服务器,地址是:ws://127.0.0.1:9229/78637688-e8e0-4582-80cc-47655f4bff66为什么调试器要启动一个websocket服务器?debugger的意思就是在某个地方停下来,你可以单步调试,看看环境中的变量。那么如何设置断点,如何暴露当前上下文的变量,就是通过启动一个websocket服务器。这个时候你只需要启动一个websocket客户端连接到这个服务器就可以调试nodejs代码了。v8调试协议连接后,调试器服务器如何与调试器客户端通信?这就涉及到v8调试协议。以双方都能识别的格式进行通信,例如:在test.js的第100行设置断点:{"seq":118,"type":"request","command":"setbreakpoint","arguments":{"type":"script","target":"test.js","line":100}}然后检查当前范围内的变量:{"seq":117,"type":"request","command":"scope"}执行表达式:{"seq":118,"type":"request","command":"evaluate","arguments":{"expression":"a()"}}然后继续运行:{"seq":117,"type":"request","command":"continue"}这样客户端就可以告诉调试器服务器如何执行代码了。debuggerclient调试器客户端一般都有ui(当然也可以通过命令行中的命令来调试,但一般没有)。常见的js调试客户端有chromedevtools和vscodedebugger等,我们写一个简单的js脚本,通过node--inspect-brk运行:可以看到它是从9229端口开始的,然后我们通过两种方式连接上客户。chromedevtools在chrome地址栏输入chrome://inspect,然后点击configure配置目标端口:填写刚才的9229端口:然后可以看到chrome扫描到了目标,点击inspect连接调试器服务器。之后可以设置断点、单步执行、执行表达式、查看作用域变量等,这些功能都是通过v8调试协议实现的。vscode调试器在vscode中编写代码,在chromedevtools中调试比较麻烦,vscode也实现了调试器支持,可以直接使用vscode进行调试。使用vscode调试能力的方法是修改项目根目录下的.vscode/launch.json配置。attach点击右下角按钮添加配置项。这里选择nodejs的attach:因为已经通过node--inspect-brk启动了websocket的debuggerserver,那么你只需要启动websocketclient,然后attach到9229端口即可。点击左边的按钮连接即可调试器服务器并开始调试:启动,首先通过node--inspect-brk启动调试器服务器,然后添加vscode调试配置进行连接。太麻烦了。你能把这两个步骤结合起来吗??当然,只要添加一个launch配置即可:这里的type是launch,即启动debuggerserver,并启动一个debuggerclient连接到server。运行的程序是根目录下的index2.js,也可以设置stopOnEntry停在第一行。点击Debug,可以看到js文件可以调试成功。Vscode会启动调试器服务器,然后启动调试器客户端自动连接到服务器。我们不需要关心这些。这样我们就可以成功的使用vscode调试器来调试nodejs代码了。vscode调试器高级调试器客户端是最常用的vscode。这里我们将重点介绍各种场景下vscode调试器的配置。如果sourcemap调试的是ts代码,一定不能调试编译后的代码。它必须能够映射回源代码。这就是sourcemap所做的。所有的调试工具都支持sourcemap,比如chromedevtools和vscodedebugger,都支持在文件末尾解析sourcemapurl://#sourceMappingURL=index.js.map这样在调试index.js的时候,如果由ts编译,会自动找到对应的ts。当然,如果在调试配置中直接指定了ts,那么要能够调试,还需要配置outFiles,告诉vscode去哪里找sourcemap。这样ts源码中设置的断点和编译后的js中设置的断点就可以生效了。多进程调试当代码中有子进程时,有第二个控制流,需要启动另一个调试器。比如基于electron的vscode,需要启动一个主进程和一些渲染进程。launch启动主进程,后面附上渲染进程。主进程启动时,使用--remote-debugging-port指定子进程自动时调试器服务器的端口。outFiles指定sourcemap的位置,这样就可以直接调试ts源码了。runtimeExecutable用vscode的runtime代替nodejs(一般不用设置)。然后后面启动渲染进程,我们通过参数配置它,它会在9222端口启动,那么只要挂在那个端口上,就可以调试进程了。vscode支持多目标调试,即在vscode中可以同时启动多个调试器。可以切换不同的调试器来调试不同的进程。综上所述,debugger的使用是一项很重要的能力,对于提高nodejs的水平很有帮助。nodejs调试器的原理是js引擎会启动调试器服务器(websocket),等待客户端连接。我们可以通过各种调试器客户端连接调试,比如chromedevtools和vscodedebugger。调试nodejs代码更多的是使用vscode调试器(当然有时也使用chromedevtools调试,基于chromedevtools的内存进行内存分析,定位内存泄漏时很有帮助)。vscode调试器的使用主要是在.vscode/launch.json中添加调试配置。调试配置分为launch和attach两种:launch会启动debuggerserver并使用debuggerclient连接attach,只是启动debuggerclient连接已有的debuggerserver,所以需要指定端口。具体的配置项比较常用:outFiles指定sourcemap的位置,用于调试ts源码等需要编译的代码stopOnEntry在第一行停止args,指定一些命令行参数,需要指定,比如vscode或者其他运行时基于这些配置我们可以调试各种场景下的nodejs代码需要编译或者多进程。毫不夸张的说,如果熟悉了debugger的使用,那么看懂各种nodejs代码就会容易很多。希望本文能帮助大家理解debugger的原理,并能够使用chromedevtools或者vscodedebugger调试nodejs代码。了解如何使用sourcemap和多进程进行调试。
