Supercharge Your Node Productivity With Debugging

By Robbie | November 17, 2021

Introduction

This tutorial will show you how to debug a NodeJS express app using Visual Studio Code. You don’t need to be a node expert to do debugging, beginner level knowledge is all thats required.

Why you should use a real debugger instead of console.log()

Back when I was a mid level engineer at Symantec, learning how to use a debugger supercharged my productivity. I could do in a couple of hours work that might have taken me a day to do. Fixing bugs and building out features was much easier.

I’ve found debugging especially useful when exploring unfamiliar codebases that I didn’t write. You can easily see the results of even the most complex logic written in weird ways. Its much easier to reason out complex, convoluted logic when you can run it line by line and see how things change.

If you’ve ever used console.log() to print a value to the console, you might know how tedious it can get if you are trying to debug something complex. It prints one value at a time and you need to write a new console.log() statement for each value you want to see. If the value you are looking at changes, you need to console.log() it again. Its a bit like poking around with a blindfold or in the dark.

None of this is necessary with a real debugger. Set a breakpoint in your code then run your app. When your app reaches the line you set a breakpoint on, you’ll be able to see all variables in scope in the debug tab. With just one action, you can now see everything instead of just one value at a time.

I started with just debugging my own application code but as time went by and I became more senior, I found I could get great insights by debugging framework code (such as the code for express itself). I was able to find answers to questions that weren’t even listed in the documentation.

Prerequisites

You’ll need to have both Visual Studio Code and NodeJS installed for this guide. If you want to run and debug your app with a public URL instead of just localhost, you’ll also need expose.sh.

Example express app

I recommend using my express example app, the entire code is shown below

// app.js
const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
    const foo = "bar";
    const bar = "baz";
    const one = 1;
    const two = 2;
    const three = 2;
    const five = two + three;

    res.send('2 + 3 = ' + five);
});

app.listen(port, () => {
    console.log(`Example app listening at http://localhost:${port}`)
});

Create a new folder somewhere on your device, then copy and paste this code into a file with the name app.js.

Set up your project with npm init, then follow the prompts.

Then run npm install --save express to install the express dependency.

You can run the code with node app.js. Hit http://localhost:3000 in your browser and you’ll immediately see this code has a bug because the output is not correct. wrong output

But don’t fix it yet. You could look at the numbers and work out in your mind what the problem is. Instead, we’ll use debugging to make it very easy to spot the problem, saving your brain.

To start with, you’ll need to set up Visual Studio Code (vscode), an open source IDE from Microsoft. If you don’t yet have it, grab a free copy from code.visualstudio.com. There are versions for Linux, Mac and Windows.

Set up vscode

VSCode is one of the easiest IDEs out there to set up debugging for, because its controlled by a simple config file. This means you can just copy and paste the config from a guide like this one, without needing to set it up manually or click lots of settings like you might need to do with other IDEs.

Create a folder with the name .vscode

Then create the file .vscode/launch.json and paste in these contents:

// .vscode/launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch Express App",
            "program": "${workspaceFolder}/app.js",
            "request": "launch",
            "skipFiles": [
                "<node_internals>/**"
            ],
            "type": "pwa-node"
        }
    ]
}

Set a breakpoint

A breakpoint is a place you set in your code where you want your application to pause, so you can inspect local variables and the general state of your app. In vscode, a breakpoint represented by a red dot to the left of the line number you want your app to pause on. Breakpoints are set by simply clicking the area to the left of the line number.

We can see that some numbers have been added incorrectly, so set a breakpoint on the res.send('2 + 3 = ' + five) line, by clicking on the area to the left of the line number. A red dot should appear where you clicked, like the one on line 14 below: breakpoint

We want to get to the bottom of why the value of five is 4 and not 5, like it should be.

Start your app with debugging

Click on the debug icon at the left of the vscode window to open the “Run and debug” pane. It looks like this:

debug pane

You’ll see launch express app at the top of the left pane.

Click that little green arrow icon to the left of “Launch Express App”.

Your express app will now launch inside vscode with full debugging support. In the “Debug Console” pane at the bottom of the vscode window you’ll see it start up:

debug console

The app is now being run within vscode with debugging support.

Trigger your breakpoint

With the app running in vscode, go to http://localhost:3000 in your browser (or just click that link).

The breakpoint will then be hit. It will look like this: breakpoint hit

There are a few things going on here, so lets explain below.

To the left under RUN AND DEBUG you’ll see the list of local variables. req is the express request object, res is the express response object. These are useful to look at if you want to see query parameters and data posted to your app.

You can see all local variables and their values in scope at the line your breakpoint is on. To see all of this information using console.log() you would have to log each variable one by one. With the debugger and a breakpoint you can see everything instantly.

Above the res.send line, i’ve done some basic arithmetic. You’ll see the results of this in the list of local variables. For example the value of two is 2.

Now look at the value of three. Clearly, it should be 3 not 2, so there is the bug. Update the value of three to 3, then stop and restart the application and the output will be correct. correct output

Debug with a Public URL

You’ve learned to debug with a localhost URL, only accessible from your computer. Using expose, with a single terminal command you can give your locally running express app a public HTTPS URL which you can share with others. All traffic to this public URL will be automatically routed to localhost through a secure tunnel.

Why would you want to do this? Lets say you are building an API for an app and you are working with a front end (e.g. React) developer who will integrate with your API. This is a very common use case for express.

You could set a breakpoint, then ask the React developer to trigger his app to call your API. You can then inspect the request and update your API to handle it.

Other uses are Webhooks. If you ever have to do a webhook integration, you can configure your public URL with the webhook provider and trigger them to make a request to your locally running app, which you are debugging in vscode.

You can now see exactly what your webhook provider is sending and you didn’t even need to read (or even understand) their documentation. Now you know exactly what code to write to make use of that request. Regardless of how good or bad their documentation is, you now know what to do.

To install expose, go to the Installation Page and follow the instructions shown. Its a copy and paste install for Linux and Mac. A downloadable exe is available for Windows.

Run expose 3000 and you should see output like:

$ expose 3000
http://mofgjp.expose.sh is forwarding to localhost:3000
https://mofgjp.expose.sh is forwarding to localhost:3000

Now with the breakpoint still set and your app running in vscode, go to the HTTPS URL shown in your browser.

The breakpoint will be hit as if you have just made the request to localhost. If you want to get fancy, try hitting this URL from another computer or your phone and the breakpoint will still be hit.

You can now share this URL with other developers you are integrating with, webhook providers and other people you want to share it with.

Using the debug console

A nice little feature of the vscode debugger is the debug console. It opens up at the bottom of the window when you start debugging inside a pane with the title DEBUG CONSOLE. If you’ve ever used the console inside devtools for your favorite web browser, this is pretty much the same thing but for back end NodeJS code.

Sometimes you might want to try out an expression without modifying your code. In the debug console, try typing in one + three. The result 4 will appear in the console: one plus three

You can run any JavaScript code inside the debug console. You can also run functions. Lets say a function you are calling is not doing what you expected it to do. You could try running it with different parameters inside the debug console until you get it to behave how you want, then update your code accordingly.

Step to the next line

Set a new breakpoint at the line const foo = "bar". Launch your express app in vscode, then hit the URL in your browser.

The breakpoint will be hit. A useful feature of the debugger is the ability to run to the next line, so you can effectively run your app line by line.

To step to the next line, click the “Step Over” icon, which looks like this: breakpoint hit.

If you keep clicking it, your app will keep running to the next line until there are no more lines of the current method to run.

Conclusion

Debugging can supercharge your productivity as a NodeJS developer. You’ll be able to fix bugs faster and spend way less time figuring out unfamiliar code. Instead of logging values one by one with console.log, with debugging you can now see everything at once.

Once you learn debugging, you’ll never need to use console.log for debugging again.

Happy Coding!