Chrome DevTools - Debugging Node.js Application Using ndb

September 10, 2018 7 min read Chrome DevTools Node.js

Google Chrome Labs have improved our debugging experience by releasing a new debugger for Node.js. In this post, we'll cover the capabilities of ndb as a debugging tool.

As some of you might remember, a headless native debugging tool was supported in Node.js for a long time:

Demonstrating the native Node.js debugger

Demonstrating the native Node.js debugger

It used a deprecated protocol, which was called V8 debugger protocol. This native tool wasn’t a full-featured debugger, but enabled simple inspections.

Over the years, an improved debugging tool showed up. It was based on the V8 debugger protocol and the developer tools of Blink (the Webkit-based rendering engine of Chromium). This tool enabled us to debug our Node.js application through the DevTools of a WebKit-based browser such as Chrome and Opera! Yes, we’re talking about node-inspector. It was very useful because we could benefit from some DevTools capabilities.

As part of Node.js v6.3.0, a new experimental feature came out - the V8 inspector, which brought a much powerful debugging protocol that integrates with Chrome DevTools and supports up-to-date features like blackboxing, profiling, workspaces, source maps and more. Furthermore, it didn’t depend on the deprecated V8 debugger protocol, rather the Chrome Debugging Protocol. Thus, it could be connected with inspector clients, for instance - a Chromium-based browser, VSCode, WebStorm/IntelliJ. Connecting it to a Chromium-based browser is pretty simple - we just had to navigate to the output URL of the command: node --inspect script.js.

Perhaps you’ve heard that on July 20th - a new tool called ndb was released as an open source project! 🚀

Well, it’s cool there is another way to debug a Node.js application - but what’s the point of an additional debugging tool? 🤔

Motivation

Let’s start by attaching the official definition of ndb:

ndb is an improved debugging experience for Node.js, enabled by Chrome DevTools

From the definition above, we can presume implicitly that:

  1. ndb improves the debugging experience by providing an easier workflow and exclusive capabilities.
  2. ndb is based on Chrome DevTools, which means it uses the Chrome Debugging Protocol, similar to the V8 inspector.
  3. ndb is part of Google Chrome Labs and maintained by the Google Chrome team.

So you might think that ndb just enables extra features compared to the V8 inspector - however that’s not completely the case.

Obviously, the V8 inspector and Chrome DevTools integration assumes that two fundamental things are installed: Node.js v6.3.0+ and a Chromium-based browser. What if we prefer using other browsers on daily basis or just prefer to not install a Chromium-based browser, but still want to be able to debug a Node.js application regardless of our editor?

Well, we haven’t noted anything about the dependencies of ndb yet, so that’s a good time - ndb depends (among other things) on a very popular package, which is called Puppeteer. Puppeteer, for those who aren’t familiar with, is an API for controlling Chromium over the Chrome DevTools Protocol.

Puppeteer is a dependency of ndb

Puppeteer is a dependency of ndb

When ndb installs Puppeteer, the most recent version of Chromium is downloaded and placed inside node_modules. In addition, the downloaded version is compatible with the host operating system.

So here is an additional benefit - ndb doesn’t depend on a local installed Chromium-based browser (or its version) which belongs to the host machine, because it installs that independently. This makes ndb a browser agnostic debugger, compared to the V8 inspector.

Notice that it increases the size of node_modules thus some of you might find it as a downside.

Alright, let’s start exploring the debugging experience with ndb! 🕵️

Exploring ndb

The first step is to create a basic Express application (an app.js file) which is going to be used for demos:

This project has a single npm script for running the application:

Now we’re truly ready to start.

Disclaimer: We’ll go over capabilities which are exclusive to ndb, but non-exclusive as well. If you want to see the exclusive list, check this out. On top of that, we’re not going to compare the debugging experience of ndb with other inspector clients like VSCode or WebStorm - simply focus on ndb.

How to Install

First up, we should certainly install ndb globally or locally. Installing it globally will standardize a way to debug any Node.js application, regardless the editor or browser that we usually use.

Let’s do that:

npm install -g ndb

Note: In case we want to use ndb inside an npm script, it should be installed locally as devDependency.

At this point, we’re able to run the debugger from any Node.js project!

Opening ndb

There are a couple of ways to open ndb - let’s cover them.

1️⃣ - Executing a file directly

We can open ndb through executing a Node.js script file directly, simply by:

ndb app.js

Notice that we use ndb instead of node.

Debugging a script file directly

Debugging a script file directly

2️⃣ - Executing an installed binary

Sometimes we want to debug a script of our application using a globally or locally installed package, which brings its executable binary file with itself - such as npm scripts, task runner, test runner and so on.

It’s possible easily by attaching ndb before:

ndb npm start

In the above command, we use the global npm to run an npm script right into ndb. Theoretically, we could run ndb webpack or ndb mocha either assuming we have the appropriate configuration for them in our project.

Note: In order to run an executable binary file of a locally installed package, we must use ndb with npx, just like: ndb npx mocha.

Debugging by running npm script

Debugging by running npm script

3️⃣ - Opening a project

It’s not necessary to execute a file or an executable binary just for opening ndb - we could do it explicitly within the project’s directory, by:

ndb .

This command gives us a freedom to perform stuff before executing a script - like placing breakpoints, editing the files or anything else.

Debugging a project

Debugging a project

From this point on, we’ll assume that ndb is opened using the third way and that the application runs in the background.

Placing Breakpoints

Placing breakpoints while we debug is quite straightforward. All we’ve to do is applying them on the relevant code:

Placing a breakpoint on the HTTP response

Placing a breakpoint on the HTTP response

Notice that we can place breakpoints before the modules are actually required!

Working with Files

With Workspaces of Chrome DevTools, we can create and edit files within the project and save them to the local file system:

Changing the source code of a script file

Changing the source code of a script file

Running npm Scripts

If the project contains some npm scripts, these are available through ndb inside a dedicated pane:

Running an npm script

Running an npm script

Pay attention - the application which had been run in the background was terminated for the demo above.

Built-in Terminal

The experimental terminal which was added to Chrome DevTools is accessible through ndb either:

Opening the built-in terminal panel

Opening the built-in terminal panel

As you probably guess, it uses the local terminal environment settings of the host machine.

Blackboxing

By default, ndb blackboxes external sources, like node internal libraries, which aren’t really interesting while we debug our project:

Blackboxing the module loader of Node.js

Blackboxing the module loader of Node.js

Processes Pane

This is a pane which lists the current running Node.js processes by ndb. Moreover, a child process is attached automatically to its parent process - so it’s absolutely plain to follow and even terminate both:

Terminating a child and parent process by single click

Terminating a child and parent process by single click

Snippets

Snippets are little scripts that we can create, execute and debug immediately through Chrome DevTools and these are supported also in ndb:

Creating and executing a snippet

Creating and executing a snippet

Process Object

Of course that Process, the global object of Node.js, is accessible in ndb’s Console:

Logging `process` object to Console

Logging `process` object to Console

Summary

We focused today on the debugging experience for a Node.js application with ndb.

Here are several important points:

  • The V8 debugger protocol (the old native debugger) is deprecated.
  • The node-inspector debugger is deprecated.
  • Node.js v6.3.0 arrived with the V8 inspector which is based on Chrome Debugging Protocol.
  • The V8 inspector could integrate with various inspector clients such as a Chromium-based browser, IDEs/editors and other clients.
  • The integration between V8 inspector and Chromium-based browser provides us up-to-date DevTools capabilities, assuming that such browser is installed locally.
  • ndb became an open source project on July 20th.
  • ndb has some exclusive capabilities, beside the supported up-to-date DevTools capabilities.
  • ndb uses the Chrome Debugging Protocol, much like the V8 inspector.
  • ndb is maintained by the Google Chrome team.
  • ndb depends on Puppeteer, which downloads a local version of Chromium into node_modules.
  • Thanks to Puppeteer, ndb is a browser agnostic debugger.
  • Using ndb, we’re able to debug any Node.js application regardless the browser or editor we use.
  • ndb should be installed as devDependency in case we want to use it inside an npm script.
  • There are three different ways to open ndb.