Debugging JavaScript/TypeScript Node apps with Chrome DevTools, VS Code and WebStorm šŸžšŸ”«

Written by andrerpena | Published 2018/04/15
Tech Story Tags: javascript | debugging | typescript | debugging-javascript | debugging-typescript-node

TLDRvia the TL;DR App

This article covers using the Node Inspector to debug both JavaScript and TypeScript Node.js applications using Chrome DevTools, Visual Studio Code and WebStorm.

As described in the Node.js debugging guide, Node.js 6.3 introduced the ā€œinspectā€ and ā€œinspect-brkā€ CLI arguments (node --inspect [file] or node --inspect-brk[file] ) that make node to listen via WebSockets for diagnostic commands as defined by the Chrome Debugging Protocol. This protocol has replaced the V8 Debugging Protocol (Now known as Legacy Protocol), which became obsolete on Node 7.7.

Additionally, the Node CLI also provides a ā€œrequireā€ argument meant to preload modules (node --require [file]), but most importantly, for debugging purposes, it allows 3rd party libraries to hook into the ā€œrequire.extensionsā€ module and make Node able to compile and generate source-maps for other languages like TypeScript. For debugging TypeScript weā€™ll use ts-node. Itā€™s important to remember that in your tsconfig.fileĀ , that can be generated by running tsc --initĀ , you should have ā€œsourceMapā€: trueĀ , which is the default value.

Iā€™ve prepared a GitHub repo with a simple Express app that calculates Fibonacci sequences. I recommend you to clone it to follow along, but this is not a requirement for continuing reading this article.

$ git clone https://github.com/andrerpena/medium-node-inspector-tests.git

$ cd medium-node-inspector-tests

$ npm i

Iā€™ve also created scripts for all the commands weā€™ll run on this article. If youā€™re reading this without cloning the repo, use the following as a reference:

After your environment is set up, you should be able to npm start and access localhost:3000/[n] to see the Fibonacci sequences.

Because I wanted to showcase both JavaScript and TypeScript debugging, Iā€™ve written the index.ts file first and the JavaScript version has been generated by tsc so it looks a bit ugly. You obviously wonā€™t have this problem if your code is primarily written in JavaScript.

Running in DebugĀ mode

Weā€™ll explore 2 modes of debugging. Using --inspect and --inspect-brk. The difference is that the later will not actually start the execution of your code before an agent like Chrome DevTools is attached, and once itā€™s attached, it will automatically break at the first user-code line.

When a Node.js app is started in ā€œinspectā€ mode, 2 important things will happen:

  1. An UUID will be assigned to this debugging session and a WebSockets end-point will spin up at ws://127.0.0.1:9229/[UUID]Ā . This end-point will stream real-time events with the current state of the running code.
  2. An HTTP end-point will spin up at [http://127.0.0.1:9229/json](http://127.0.0.1:9229/json)Ā . This allows agents like the Chrome DevTools to know about every running Node session and their respectiveUUIDĀ .

You can curl [http://127.0.0.1:9229/json](http://127.0.0.1:9229/json). More information here:

Debugging JavaScript using the ChromeĀ DevTools

Run:

npm start:debug // if you're on the suggested repo or...node --inspect index.js // ...otherwise.

You should see something like this:

You can see a WebSocket server has started on port 9229Ā . You can also notice the UUID is 5dc97...Ā . Each session will have itā€™s own and every time you restart your server this will be different.

Next step is opening Chrome and entering Chrome://inspect on the address bar. You should see something like this:

Again, Chrome can automatically detect running sessions by inspecting [http://127.0.0.1:9229/json](http://127.0.0.1:9229/json)Ā . Now click Inspect to start debugging. A new DevTools window will show up. You can now navigate to the desired file, (e.g. by pressing Cmd + P on Mac), place your break-points and have fun šŸ˜„:

If instead, you run:

npm start:debug:brk // if you're on the suggested repo or...

ā€¦ youā€™ll notice that localhost:3000 will not be immediately available. This is because, due to the--inspect-brk argument, Node will only start executing your code after the DevTools or another debugging agent is attached to give you the chance to place break-points beforehand. After clicking InspectĀ , you can now refresh localhost:3000 and it will automatically break on the first line of your code.

Debugging TypeScript using the ChromeĀ DevTools

It should be almost the same thing we did with JavaScript except that now we should include --require ts-node/register when running Node. Run:

npm start:debug:ts // if you're on the suggested repo or...node --require ts-node/register index.ts // ...otherwise.

And you should see this:

And when you start inspecting on Chrome://Inspect you should now see 2 versions of each TypeScript file: One with source-maps (marked as [sm]) and another one without. Of course, place your break-points on the [sm] ones šŸ˜„:

Everything else should work exactly the same.

Debugging JavaScript using the Visual StudioĀ Code

Just by selecting the target JavaScript file, clicking on the Debug tab (Shift + Cmd + D on Mac) and hitting the ā–¶ļø button should be enough to start debugging the current JavaScript file even without selecting any launch configuration. VS Code will automatically start Node with the --inspect parameter and attach to it.

You can also very easily create a launch configuration for attaching to a Node process running from the terminal. The VS Code auto-completion for configurations is amazing. This is how the configuration should look like. Remember that 9229 is the default port for the Node inspector:

Notice that the above configuration doesnā€™t specify the UUID of the Node session. VS Code, just like Chrome DevTools, will inspect ws://127.0.0.1:9229 and automatically attach to the current running session if thereā€™s only one.

After the configuration is in place, run the usual start script from the terminal:

npm start:debug // if you're on the suggested repo or...node --inspect index.js // ...otherwise.

ā€¦ and then select Attach as the launch configuration and hit the ā–¶ļø button:

Debugging TypeScript using the Visual StudioĀ Code

VS Code, when using a configuration "type":"node" will not allow the program to be aĀ .ts file (at least as this article is being written), then youā€™re left with 2 options: You can either run ts-node passing aĀ .ts file as the argument (${relativeFile} returns the currently focused one)ā€¦

ā€¦ or you can specify the runtimeExecutable to be NPM (instead of the default: node) and pass a script name as an argument. Both of them have the exact same effect:

If you want, instead, to attach to a running TypeScript process spawn from a terminal, it is the exact same script we used for pure JavaScript. Just run the usual script on your terminalā€¦

npm start:debug:ts // if you're on the suggested repo or...node --require ts-node/register index.ts // ...otherwise.

ā€¦ and then attach using the same script we used for pure JavaScript:

Debugging JavaScript usingĀ WebStorm

On the top-right corner of WebStorm thereā€™s a dropdown where you can set up Run/Debug ConfigurationsĀ . Click on it and then select the āž• sign to see a list of all available configurations. Select Node.jsĀ , give it a NameĀ , and in the JavaScript file field, fill in your entry-point file. That is it. You can now hit the šŸž button and the debug session should start.

Debugging TypeScript usingĀ WebStorm

In order to Debug TypeScript, the process is exactly the same as for JavaScript, except that, in the Node Parameters field, you should fill --inspect --require ts-node/register and select your TypeScript file in the JavaScript file field. You can start the debugging session as usual by hitting the šŸž button.

I hope you enjoyed it and happy debugging šŸžšŸ”«!

About theĀ Author

Iā€™m AndrĆ© Pena, I like writing and building stuff. Recently I built: https://remoted.io, a remote job aggregator for developers, check it out! šŸ’—


Published by HackerNoon on 2018/04/15