Node.js debugger in practice

How to setup debugging in a Node.js environment? Official resources such as the debugger command reference and the debugging guide aren’t end-to-end practical guides (as the name might suggest).

By debugging is meant the traditional sense: The execution of a target program stops at every breakpoint or debugger; statement, giving control to a distinct debugger process. The debugger allows to 1) set breakpoints 2) resume or control the execution of the program and 3) inspect the program state.

There are a few common contexts of debugging: The target program can be the main program, but also the tests. The debugger can be the Node CLI debugger utility but also your favourite IDE, Google Chrome or any compliant system. Using an IDE allows setting breakpoints without touching the code, increasing your efficiency by an order of magnitude.

In the following we review how to debug in those different contexts.

Setup debugging

Debugging requires the target program to run on an environment which allows the execution to be controlled by a debugger. In our case, Node makes this possible when launched with one of the three inspect flag variants: inspect, --inspect and --inspect-brk.

… with the Terminal

next, continue, ...: The full list of commands that are available via the debugger is in the debugger reference.

Debugging the Program

node inspect main.js

This variant using inspect has the following effect: It 1) pauses the execution at the first line, 2) uses the Node built in CLI debugging utility as the debugger, and 3) attaches the Terminal to the utility.

Debugging the Tests

What if you need to debug your program using the tests as the entry point?

Testing frameworks usually provide with a wrapper around the node binary to run the tests (e.g. jest). It is specific to each framework how to get it to run node in debug mode.

In the case of the Jest framework, it is documented here and it works this way: Instead of running jest , run:

node inspect $(which jest) --runInBand
  • --runInBand runs the tests in a single threaded fashion.
  • $(which jest) returns the path of the jest binary. If it is installed locally to the project, it would be node_modules/.bin/jest.

… with a Remote Debugger

We saw how to debug the main program or the tests with the Terminal. This is arguably the traditional and most simple way to debug, but it is just a specific case of debugging. Any compliant program can attach to Node (if Node runs in debug mode) and act as a debugger.

To make this possible, run the program as following:

node --inspect-brk main.js

Contrary to inspect, --inspect-brk doesn't involve the Node CLI debugging utility or the Terminal. Instead, it launches Node in debug mode but it expects a debugger to attach.

Compared to --inspect, the --inspect-brk variant pauses the execution at the first line of code. This gives the opportunity for a debugger to attach instead of the program running and possibly ending before the debugger even intervenes.

Use an IDE as debugger

Debugging with an IDE allows declaring the breakpoints without modifying the code or using set breakpoints debugger commands. Instead, one can just click on the lines. Behind the scene, the IDE uses the inspector API provided by the runtime (Node) to register the breakpoints at startup.

With VSCode, it is straightforward to configure and use the integrated debugger:

  • Configure VSCode by searching for debug node in the settings, and set Auto Attach to on.
  • Run the node command given above in the VSCode integrated Terminal (View > Terminal).
  • Use the View > Debug pane and the Debug Console to interact. You can set breakpoints by clicking on the left of the line numbers in the code.

As a side note, VSCode allows to save launch configurations. This allows to launch the program or the tests with specific settings in one click from the View > Debug pane. How to proceed is explained in the official documentation.

Use Google Chrome as debugger

Google Chrome also integrates a Node debugger:

  • Run the node command given above.
  • Open Google Chrome and navigate to chrome://inspect.
  • Click Devices > Open dedicated DevTools for Node.

Ending note

Other options of the inspect flag allowing further configuration are available and described in the debugging guide and in the debugger command reference but they don’t change the philosophy.

When starting coding in a new language or environment, it’s nice to just jump to writing code and skip all boilerplate knowledge and DSLs.

Very quickly though, knowing the environment can save you a lot of time and anxiety. Managing the runtime versions (e.g. in Ruby), understanding the import / export system, knowing how to write and launch the tests, and debugging: Demystifying those operations can end up changing the way one works, improving development efficiency and fun by an order of magnitude.

View Original