Better Debugging in Reaction

I've got another architecture post in the works, but today, I wanted to give a sneak peek into an awesome new feature that was just released into Meteor 1.6 and coming soon to Reaction. As of Meteor 1.6, you can now debug server code using the --inspect flag. Introduced in Node.js 7, the new
--inspect flag permits fast debugging of code using Chrome DevTools, VS Code, and other tools compatible with the inspector.

Meteor's latest release comes with a host of new features, the direct result of upgrading to Node.js 8 and npm 5. If you want to read more about Meteor 1.6, check out the release announcement from the official Meteor blog. You don't need to worry about upgrading your own version of Node or npm; Meteor (and Reaction) keeps things tidy by shipping with pinned versions of the two. If you're interested in how and why this is done, be sure to check out "Know Your Node.js" by Jesse Rosenberger.

In this blog post, I'll show you how to configure the --inspect flag on Reaction through Meteor. I'll also run through some of the different tools you can use to get started.

Configuration

Run Reaction with the new --inspect flag

In the next few weeks, we'll update the reaction-cli command to support this flag, but if you're itching to try this out before we release Reaction v1.6, then here's how you do it.

First, check out our WIP branch, meteor-1.6. You can do this by entering the command git checkout meteor-1.6. After that, run Reaction using the underlying Meteor commands. Again, once we update our reaction-cli, it'll be much more straightforward, but for now, this is the best way to try it out.

From your Reaction directory, go ahead and run:

$> meteor run --inspect

Once this process has started, Node opens a WebSocket to listen for a debugger on port 9229 by default. Once you've successfully attached a debugger, you'll see the Debugger attached message in your terminal. Now, you're ready to debug!

Inspector Clients

In this post, I'll be covering two different code-debugging clients: Chrome DevTools and VS Code. If you know of any other tools, or if you have any other tips, feel free to drop a note in the comments; I'd love to learn more about any new tools or techniques in the ecosystem.

Chrome DevTools

Chrome DevTools is probably the easiest way to get started using
--inspect. Do you use Chrome as your web browser? You're pretty much ready to go. Here's how you do it.

First, visit chrome://inspect in Chrome.

Then, click the link that reads, "Open dedicated DevTools for Node." This opens up a stand-alone DevTools console that connects to any Node debugger instances that have been opened.

To set breakpoints, open up the source tab in your DevTools window and navigate to a file you'd like to set a breakpoint for. You're currently debugging the Reaction server, so you'll only have access to code that runs on the server. In my examples, I set some breakpoints in the Products publication, which gets called whenever a client connects to the product grid on the index route. You can set them anywhere, though.

Similar to the client, if you want to access the console and the sources at the same time, hit esc while you're on the sources tab to open the "drawer" version of the console. When DevTools arrives at a breakpoint, it highlights the line of code. From there, you'll be able to use all of the debugging tools you might find in the client for that particular line of code.

Here's a gif of me running through the call stack, step-by-step:

DevTools also exposes the CPU Profiler and the Memory Profiler, which are slightly more advanced topics that I'll try to cover in a future post.

VS Code

NOTE: You can only have one debugger connected at a time, so if you've already connected to DevTools, then you'll need to disconnect before you can connect with VS Code.

Setting up VS Code and connecting it to the Node debugger is only slightly more complicated than using DevTools. But once it's set up, it can easily become a part of your regular workflow. To use the debugger, VS Code requires a launch.json file. In the root of your project directory, add a .vscode/launch.json file.

My file looks like this, which I borrowed heavily from a Meteor forum post on Meteor 1.6 server debugging with VS Code:

{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "node",
            "request": "launch",
            "name": "Reaction Server",
            "cwd": "${workspaceRoot}/",
            "runtimeExecutable": "${workspaceRoot}/.meteor/local/dev_bundle/bin/npm",
            "restart": true,
            "timeout": 30000,
            "stopOnEntry": false,
            "sourceMaps": true,
            "protocol": "inspector",
            "port": 9229
        }
    ]
}

Port 9229 is the default Node inspector port, but if you switch to another one, eg. --inspect=5000, then you'll need to adjust the port in your launch.json file.

Once this file is set up, open the debug panel in VS Code and click the Play icon to start the debugger and attach to the designated port.

So what's the difference between DevTools and VS Code? There is one main advantage: if you use VS Code as your primary editor, then you can add breakpoints to your code from within the main editor window.

In this example, I've added a couple breakpoints to the Products.js publication file in server/publications/collections. When I open a browser and request products from the grid, the debugger kicks in at those breakpoints:

The VS Code debugger comes with a lot of the same features as DevTools does, and these features are directly integrated into your editor. That said, DevTools does come with several features that I would miss if I only used VS Code. For example, DevTools shows the values of any variable in the local scope inline in the code. VS Code only includes the variable in the variables panel. Not particularly onerous, but it's an extra step.

VS Code allows you to step through the call stack; it also loads up the correct file in the editor view as you step through. You're already in your editor, so it's an extra nice touch. Having the ability to enable and disable specific breakpoints—all exceptions or uncaught exceptions, for instance—from the breakpoints panel is another cool VS Code feature.

VS Code doesn't include any advanced features such as the CPU or Memory Profiler, unfortunately. Maybe this is something that could be added through plugins, if that hasn't been done already. If you'd like to share how you use VS Code for debugging, please comment on this post below!

Other Clients

The Node.js docs include a list of other clients that can connect to the inspector. Check these out if you need something that DevTools or VS Code doesn't offer.

Conclusion

I hope this gets you excited about what's coming in v1.6. I believe that this will not only make every developer's life a little easier, it'll also make debugging on the server much more enjoyable. While we don't have a specific date set for our next release, we expect to be seeing a release candidate sometime this week. Hopefully, the official release soon follows.

comments powered by Disqus