This article will take a look at three different techniques for debugging a NestJS application with VSCode.
For a quick introduction to NestJS, check out this article.
Visual Studio Code, or VSCode, is a lightweight source code editor with cross-platform support that boasts an impressive variety of features. Among these features is excellent tooling for debugging applications, including built-in support for Node.js and TypeScript.
While the NestJS documentation is comprehensive, one of the things that it currently does not cover in-depth is debugging.
Fortunately for us, VSCode makes it very straightforward to debug both your NestJS application code and tests written using the Jest testing framework. All that’s required is a little bit of tuning.
With that in mind, let’s dive in.
Approach #1: Launch Configuration
The first approach relies on a launch.json
file included in a .vscode/
directory in the root of your workspace.
This JSON file provides configuration information that VSCode uses while figuring out how to debug your application correctly.
Check out these docs for more on configuring a launch.json
file.
The JSON file will look like this:
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Debug Nest Framework",
"args": ["${workspaceFolder}/src/main.ts"],
"runtimeArgs": [
"--nolazy",
"-r",
"ts-node/register",
"-r",
"tsconfig-paths/register"
],
"sourceMaps": true,
"envFile": "${workspaceFolder}/.env",
"cwd": "${workspaceRoot}",
"console": "integratedTerminal",
"protocol": "inspector"
}
]
}
A lot is going on in the above file, so let’s break it down attribute by attribute:
-
type– Indicates the type of debugger to use. In our case, it’s
node
but if you have a debugging extension forGo
you could set it to go, etc. -
request– The request type of the configuration. This can be either
launch
or attach (either launch a new process orattach
to an existing one) -
name – The name you want to be associated with your debugging configuration
-
args– Arguments passed to the program that is being debugged. In this case, we provide the path to our
main.ts
file that is the entry point to the application -
runtimeArgs – Optional arguments that are passed to the runtime executable. Because we are providing a TypeScript file directly to Node.js, we use
ts-node
to run the file without the manual use of the TypeScript compiler -
sourceMaps– Use source maps, if found. This is important as it allows us to step through the original TypeScript code, instead of the transpiled JavaScript
-
envFile– An optional path to a
.env
file. This is necessary if your application relies on environment variables stored in a.env
file -
cwd–The current working directory for finding dependencies and other files
-
console– Which console to use when displaying debugging output. In this case, we’re indicating we want to use the integrated terminal in VSCode
-
protocol– Which Node.js debugging runtime protocol to use. The
inspector
protocol is the latest
To use this launch.json
configuration, first set a breakpoint somewhere in your application’s code.
Then, navigate to the debug pane in the VSCode activity bar by clicking on the icon or by using the keyboard shortcut (ctrl+shift+D/cmd+shift+D
).
Finally, select the Debug NestJS Framework
configuration from the dropdown and run the debugger by pressing the start icon or using the keyboard shortcut (F5).
At this point, the code should pause at the breakpoint and allow you to debug.
Approach #2: Nodemon
The second approach to debugging NestJS is to use nodemon
in conjunction with VSCode’s auto attach feature.
As a quick refresher, nodemon
is an NPM package that is helpful when developing Node.js applications. It automatically restarts the application when changes to source code files are detected.
To start, we need to make sure we have nodemon
installed as a development dependency by running npm i --save-dev nodemon
.
With this in place, we also need an npm script in our package.json
to run nodemon
.
Specifically, we add "start:debug": "nodemon --config nodemon-debug.json
".
We’ll also need the nodemon-debug.json
file referenced in the above script as shown below:
{
"watch": ["src"],
"ext": "ts",
"ignore": ["src/**/*.spec.ts"],
"exec": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register src/main.ts "
}
The above configuration file tells nodemon
to do the following:
- Watch the code in the
src/
directory for changes - Look for files with a
.ts
extension - Ignore any files in the
src/
directory that end with.spec.ts
(our test files) - Execute a command. In the above, we use the Node.js runtime as well as
[ts-node](https://www.npmjs.com/package/ts-node)
to run our application in debug mode
The final step is to enable VSCode’s auto attach feature. This feature will automatically connect the VSCode debugger to any Node.js process that has been launched in the integrated terminal.
This feature can be turned on using the command palette (ctrl+shift+P
/cmd+shift+P
) and selecting Toggle Auto Attach
.
You can now set a breakpoint, run npm run start:debug
in the integrated terminal, and debug your application.
Approach #3: Launch Configuration for Jest
This final approach will cover debugging Jest tests in your NestJS application using a new configuration in launch.json
.
The configuration we need to append to the launch.json
file for debugging Jest is shown below:
{
"name": "Debug Jest Tests",
"type": "node",
"request": "launch",
"runtimeArgs": [
"--inspect-brk",
"${workspaceRoot}/node_modules/.bin/jest",
"--runInBand",
"--coverage",
"false"
],
"console": "integratedTerminal"
}
This configuration is similar to the first configuration we used for debugging NestJS application code, though this time it is passing the path to the Jest executable in node_modules/.bin/
to the Node.js runtime.
We are also instructing Jest to run tests serially (instead of the default of concurrently) given the --runInBand
flag in the runtimeArgs
array. We opt not to collect test coverage while debugging given --coverage
is set to false.
With this configuration set, we can set a breakpoint anywhere in our test files and run the VSCode debugger (assuming you’ve selected the new Debug Jest Tests
configuration from the dropdown in the debugging pane of the activity bar).
Closing Thoughts
While a quick console.log
statement is often useful for quick debugging tasks, it doesn’t scale well when debugging large, more complex issues. This situation is when a robust debugging setup comes in handy.
Debugging NestJS can be a challenge given the framework’s use of TypeScript and dependency injection. Fortunately for us, VSCode’s debugging tooling makes this a relatively painless experience.
Hopefully, this article was informative and simplifies debugging on your next NestJS project.
As always, I’d love to hear any thoughts and feedback about NestJS/VSCode/debugging. Until next time, thanks for reading.