Debugging Node.js apps with Visual Studio Code debugger
Rather than doing it with console logs, debugging with a debugger and breakpoints is recommended. VSCode provides a built-in debugger for JavaScript-based apps.
This post covers configuring and running a debugger for various Node.js apps in VSCode.
Configuration basics
VSCode configurations can use runtime executables like npm and ts-node. The executables mentioned above should be installed globally before running the configurations.
A configuration can use the program
field to point to the binary executable package inside node_modules
directory to avoid installing packages globally.
Runtime executables and programs can have arguments defined in runtimeArgs
and args
fields, respectively.
A configuration can have different requests:
attach
- the debugger is attached to the running processlaunch
- the debugger launches a new process and wraps it
There are multiple configurations:
node
- runs the program fromprogram
field, and logs are shown in debug consolenode-terminal
- runs the command fromcommand
field and shows the logs in the terminal
The configuration file is .vscode/launch.json
. The selected configuration on the Run and Debug tab is used as the default one.
Launch configs
Node
Below are examples of configurations for running Node processes with the debugger.
{
"version": "0.2.0",
"configurations": [
// ...
{
"name": "Launch script in debug console",
"program": "index.js", // update entry point
"request": "launch",
"type": "node",
"skipFiles": [
"<node_internals>/**"
]
},
{
"name": "Launch script in the terminal",
"command": "node index.js", // update entry point
"request": "launch",
"type": "node-terminal",
"skipFiles": [
"<node_internals>/**"
]
}
]
}
Running npm scripts in debug mode
The debugger launches the following script in both configurations, dev
in this case.
{
"version": "0.2.0",
"configurations": [
// ...
{
"name": "Launch dev script in debug console",
"runtimeExecutable": "npm",
"runtimeArgs": [
"run",
"dev"
],
"request": "launch",
"type": "node",
"skipFiles": [
"<node_internals>/**"
]
},
{
"name": "Launch dev script in the terminal",
"command": "npm run dev",
"request": "launch",
"type": "node-terminal"
}
]
}
ts-node
The following configurations will wrap the debugger around ts-node
entry point.
{
"version": "0.2.0",
"configurations": [
// ...
{
"name": "Launch ts-node script in debug console",
"program": "node_modules/.bin/ts-node",
"args": ["index.ts"], // update entry point
"request": "launch",
"type": "node",
"skipFiles": [
"<node_internals>/**"
]
},
{
"name": "Launch ts-node script in the terminal",
"command": "ts-node index.ts", // update entrypoint
"request": "launch",
"type": "node-terminal",
"skipFiles": [
"<node_internals>/**"
]
}
]
}
@babel/node
The following configuration will wrap the debugger around babel-node
entry point.
{
"version": "0.2.0",
"configurations": [
// ...
{
"name": "Launch babel-node script in debug console",
"program": "node_modules/.bin/babel-node",
"args": ["src"], // update entry point
"request": "launch",
"type": "node",
"skipFiles": [
"<node_internals>/**"
]
}
]
}
Nodemon
Add new configuration with Run → Add configuration option, select Node.js: Nodemon Setup
.
Update program
field to point to the nodemon executable package, and add arguments with args
field to point to the entry point.
{
"version": "0.2.0",
"configurations": [
// ...
{
"name": "Launch nodemon script in debug console",
"program": "node_modules/.bin/nodemon",
"args": ["-r", "dotenv/config", "--exec", "babel-node", "src/index.js"], // update entry point
"request": "launch",
"type": "node",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"restart": true,
"skipFiles": [
"<node_internals>/**"
]
}
]
}
Mocha
Add a new configuration, and choose Node.js: Mocha Tests
configuration.
Replace tdd
with bdd
as u
parameter and program
field to point to the mocha executable package.
{
"version": "0.2.0",
"configurations": [
// ...
{
"name": "Launch mocha tests",
"program": "node_modules/.bin/mocha",
"args": [
"-u",
"bdd",
"--timeout",
"999999",
"--colors",
"test"
],
"request": "launch",
"type": "node",
"internalConsoleOptions": "openOnSessionStart",
"skipFiles": [
"<node_internals>/**"
]
}
]
}
Attach configs
Auto Attach
should be activated in settings with the With Flag
value. In that case, auto-attaching is done when --inspect
flag is given.
The debugger should be attached when some of the following scripts are executed.
{
// ...
"scripts": {
// ...
"start:debug": "node --inspect index.js", // update entry point
}
}
Jest
{
// ...
"scripts": {
// ...
"test:debug": "node --inspect -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
}
}
NestJS
{
// ...
"scripts": {
// ...
"start:debug": "nest start --debug --watch"
}
}
Debugging basics
During the debugging, the variables tab shows local variables. The step over
option goes to the following statement in the codebase, while step into
option goes deeper into the current statement.
Log points can add logs in debug console when a certain part of the codebase is executed without pausing the process.
Boilerplate
Here is the link to the boilerplate I use for the development.