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 代码了。