One of the most essential tools any web developer needs to possess is the ability to quickly and accurately debug some code and find out why it is not behaving the way you want it to. The way you debug will depend on where in the stack your code is running. Most modern Javascript apps are built 'isomorphically' - meaning server and the client (browser).

In this tutorial, you will learn several techniques that will allow you to debug the first part of that equation, how to debug a server, or, some code that uses node and express as the server and Javascript for the front-end.

Basic Serverside Debugging in VSCode

Let's imagine you have a basic express server, in a file called test.js:

const express = require('express')
const app = express()

const PORT = process.env.PORT || 9229

app.get('/', (req, res) => {
    debugger;
    res.send(`Hello`);
})

app.listen(PORT, () => console.log(`App listening on *:${PORT}`))

To start debugging within VS when running the app from the command-line, you need to use the --inspect flag, like so:

$ node --inspect .js

After the app is up and running, you can then browse to it, using, http://localhost:9229/ and the app should stop on the debugger statement, like so:

Debugging In Chrome

Getting a breakpoint to hit on your server-side code within VS is handy in some situations. In other situations, you have complex webpages you want to debug within Chrome instead.

In Chrome, in the URL, enter “about:inspect” to open the inspect with chrome tab. Click on the 'Open dedicated DevTools for Node'.

You can also set Visual Studio debugging configurations within a launch.json. This can be checked into GIT so the configurations can be shared within the team. In the connection screen add the endpoint to your express server. Now in a normal Chrome tab, visit your page, e.g. http://localhost:9229/

My Web App Is More Complex Than A Single Script!

All the above tips are great if you have a very simple express server, but what happens if you have a complex app that you build with webpack?  For example, you may not be able to simply run a single command that points to a single JS file.

One way to make your life easier is to create a debug configuration within VSCode. To access your current project's debug configurations, in VS code, open up the debug tab. In the top left of the editor, you should see a dropdown with the word DEBUG next to it. Click the gear button and it will open the launch.json. If you have no previous configurations set-up this file will be empty. In here you can config, both client and server side configurations. A simple debug configuration that attaches to a node server would look like this:

{
    "name": "Attach node",
    "protocol": "inspector",
    "type": "node",
    "request": "attach",
    "port": 9229,
    "timeout": 600000000,
    "sourceMaps": true,
    "cwd": "${workspaceFolder}"
}

If you save this, you should see a launch.json file created. Now as long as your node application is running, when you start debugging using this configuration within VS code your debugger should now get triggered. One interesting bit to note in the code above is the really high timeout value. The apps that I've been working on take 2-3 minutes to load, without a high timeout value, the debug may fail to attach correctly. If your app runs pretty quickly then you can omit this.

Issue Connecting

Unfortunately,  sometimes getting the debugger to attach can be a pain in the ass. I've wasted hours scratching my head trying to figure out what's going on. If you find yourself in this situation, here are some other useful troubleshooting tips to consider.

In the snippet above, I'm using the default port of 9229. If you find the debugger has issues connecting, then you can try seeing what's currently attached to that process. You can do this by:

lsof -i :9229

When I run this with an app open, I get something similar to this:

COMMAND     PID    USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
node      43275 j.jones   40u  IPv4 0x43f1bcf2f601ac15      0t0  TCP localhost:9229 (LISTEN)

Using the PID from all the processes attached to the post, you can kill everything. From experience, I've found that sometimes the debugger doesn't detach correctly and this tip has saved me quite a few times.

kill -9 43275

Connect By process ID

{
     "type": "node",
     "protocol": "inspector",
     "request": "attach",
     "name": "Launch Chrome against localhost",
     "cwd": "${workspaceFolder}",
     "stopOnEntry": true,
     "port": 9229,
     "processId": "${command:PickProcess}"
}

A really handy tool when you encounter issues attaching to the debugger is to use the '${command:PickProcess}' command. When you use this and try and try to attach, VS code will prompt you to manually select which process you want to connect to.

With YARN

If you use yarn to build your solution, you can try the below snippet

 {
      "type": "node",
      "request": "launch",
      "name": "Debug Express Server",
      "cwd": "${workspaceRoot}",
      "runtimeExecutable": "yarn",
      "port": 9222,
      "runtimeArgs": [
        "<<YOUR NPM/YARN START PROJECT COMMAND>>"
      ],
      "stopOnEntry": true
}

From my testing in a big app, this took forever to launch and run. On smaller applications, it worked quite well. As you can see from all the configurations, there are numerous properties that are available to you to configure debug configuration. A full list can be found [here](https://code.visualstudio.com/docs/nodejs/nodejs-debugging). Enjoy!