跳到主要内容

11-VSCode Node Debugge配置详解

前面两节我们学习了怎么调试 Node.js、npm scripts,这节我们来过一遍 VSCode Node Debugger 的常用配置。

首先,从 attch 的方式开始:

attach​

有这样一个 Node.js 文件:

const http = require('http');

const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
data: 'Hello World!'
}));
});

server.listen(8888);

我们以调试模式启动:

然后 VSCode Debugger 添加一个 attach 类型的 Node 调试配置,端口是 9229:

点击调试启动就可以连上。

打个断点:

浏览器访问,这时候代码就会在断点处断住:

这些我们前面讲过,今天来讲一些别的配置:

restart​

VSCode Debugger 以 attach 的方式启动,是需要连接 ws 调试服务的,而连接自然就可能超时、失败之类的,这时候就需要重连。

重连的间隔和次数是可以配置的:

比如上面就是 1s 重试一次,最多 3 次:

attach by process id​

上面的 attach 方式是连接到了 9229 端口,但其实还有另一种 attch 方式,就是通过进程 id。

比如上面跑在 9229 端口的 node 进程的 id 可以通过命令查看:

发现是 98700,那么我们就可以通过这个进程 id 来 attach 调试服务:

默认值是 ${command: PickProcess} 这个会弹出一个选择窗口:

选择 98700 的那个进程,attach 即可。

当然,这里我们已经知道了进程 id,那就不需要选择了,直接指定即可:

attch 的方式讲完了,接下来来看下 launch 方式的配置:

launch​

launch 不需要我们自己以调试模式启动,只需要指定 node 程序的地址即可:

program & args​

创建个 test 文件,打个断点:

添加一个 launch 类型的 Node 调试配置:

代码会在断点处断住,然后可以查看当前的命令行参数:

命令行参数是这俩:

可以通过 args 来添加命令行参数:

runtimeExecutable​

runtime 默认是 node,其实这个也是可以改的:

VSCode Debugger 会从 PATH 的环境变量中查找对应名字的 runtime 启动。

我们前面调试 npm scripts,就是修改了这个:

比如我们可以跑 node 调试,是因为 PATH 中有 node。

我们可以安装一个 ts-node:

npm install -g ts-node

然后把 runtimeExecutable 改为 ts-node:

这时候就是用 ts-node 来跑了:

你还可以通过 runtimeArgs 给它传参数。

VSCode 内置了 launch via npm 的配置,如果你把 runtimeExecutable 换成 pnpm,那就是 launch via pnpm 了。

skipFiles​

这个配置的默认值是 <node_internal>/**

也就是跳过 node 内部的文件。

效果就是这样的:

这样就可以精简掉调用栈,只显示我们关心的部分。

把 skipFiles 置空之后,所有代码就都展示出来了:

再来测试下,我们添加这样两个文件:

在 add 里打了个断点,然后调试方式启动:

调用栈是这样的:

如果你把 index 添加到 skipFiles 里:

那调用栈就是这样了:

index.js 也被加到 skipFiles 里折叠起来了。

stopOnEntry​

这个是在首行断住,和 node --inspect-brk 的效果一样,在 chrome 调试时也有同样的配置:

console​

默认 debug 模式下,打印的日志是在 console 的,而不是 terminal。而 console 里是不支持彩色的:

这个可以通过 console 配置设置,有三个选项:

internalConsole 就是内置的 debug console 面板,默认是这个。

internalTerminal 是内置的 terminal 面板,切换成这个就是彩色了:

externalTerminal 会打开系统的 terminal 来展示日志信息:

一般情况下,用 internalTerminal 就好。

autoAttachChildProcesses​

node 里是支持多进程的,可以把一些脚本放在子进程来跑来提高性能,充分利用计算机的资源。

比如这样:

const cp = require('child_process');

cp.spawnSync('node', ['./index.js'], {
stdio: 'inherit'
});

他就是把 index.js 放到子进程来跑了。

但是默认子进程的输入输出也就是 stdin(标准输入)、stdout(标准输出)不会显示在控制台,这时候可以让它继承父进程的 stdin、stdout 就可以了。

这个输入输出当然也可以定向到别的地方。记得前面我们指定过 console 的输出位置么?

这个就是输入输出流 stdin、stdout 的重定向。

当然,这不是我们的重点,我们目的是为了能调试子进程的代码。

index.js 是这样的:

const add = require('./add');

console.log(add(1, 2));

add.js 是这样:

module.exports = function(a, b) {
return a + b;
}

我们在 add.js 里打个断点:

它是在子进程里的断点,但是跑调试你会发现能断住:

这是因为 autoAttachChildProcesses 的默认值是 true。

调试模式启动的时候,主进程会有调试端口,子进程也会有调试端口,而 autoAttachChildProcess 就是自动连接上子进程的 ws 调试服务的端口。

调用栈这里也可以看到是两级的结构,这就是 attch 到了子进程的调试服务。

如果你把 autoAttachChildProcesses 设置为 false,就会发现在子进程打的断点不会生效了。

cwd​

cwd 很容易理解就是 current work directory,当前工作目录。

也就是指定 runtime 在哪个目录运行,默认是项目根目录 workspaceFolder

比如在调试 npm scripts 的时候,指定了 cwd 就是在 cwd 下执行 npm run xxx 了:

env​

node 程序很多情况下是需要取一些环境变量的,那我们要手动设置了环境变量再跑调试么?

不用,有对应的配置,也就是 env。

比如这样:

这样在调试的 node 程序里就可以取到这些环境变量:

如果你有一个 envFile 来保存环境变量的话,也可以通过 envFile 的方式:

.env 内容如下:

在 node 代码里可以取到对应的环境变量:

presentation​

当调试配置多了以后,就会比较乱,那能不能做一些配置的分组还有排序呢?

VSCode Debugger 是支持的。

比如这样三个调试配置:

我们想把调试 chrome 的放一组,调试 node 的放一组,就可以这样写:

效果就是这样的:

大型项目里调试配置会很多,比如 VSCode,它就有很多调试配置,并用 presentation 做了分组:

总结​

这节我们过了一遍 VSCode Node Debugger 的调试配置:

  • restart: attatch 的时候可以指定尝试重连的次数和时间间隔
  • processId:除了可以通过网络端口,还可以通过进程 id 的方式 attach 到某个进程的调试服务
  • program:调试的 node 代码路径,可以通过 args 传参
  • runtimeExecutable:指定跑代码用的 runtime,默认是 node,也可以换成 ts-node、npm、pnpm 等,但要求这些命令在 PATH 环境变量里
  • skipFiles:折叠某些路径,不显示在调用栈里,比如 node 内部的一些代码
  • stopOnEntry:在首行断住,和 --inspect-brk 一样的效果
  • autoAttachChildProcesses:自动 attch 到子进程的调试服务
  • console:指定日志输出的位置,是内置的 console、terminal,还是外部的 terminal
  • cwd:跑 runtime 的目录
  • env:指定环境变量
  • presentation:对多个调试配置做分组和排序

理解了这些调试配置,就可以愉快的调试 node 代码了。