Debugging with Visual Studio Code

Quick intros for Gulp, React, and Angular

After a year of using Visual Studio Code (VS Code) I’ve finally taken the time to explore the built-in debugger. By writing this, I hope to solidify a new workflow and provide some useful information for others looking to learn about this terrific editor.

Please note that this post assumes some knowledge of traditional debugging in modern browser DevTools. I recommend this post from Brandon Morelli if you’re new to debugging and want an introduction to DevTools in the browser.


At work I’ve been building features for a complex CMS dashboard that’s transitioning from AngularJS to Angular 4. It’s a behemoth of an application that sports a fairly robust build process and a healthy mix of tooling. To facilitate the build we use Gulp which handles copying, linting, compiling, bundling and more.

In one particular build step, we lint LESS and compile it to CSS. When the stylesheets are compiled, we kick off a watcher which monitors LESS files and recompiles them anytime a change has been made. This is great when it works, but the process had begun to show signs of disrepair. The watcher was no longer recompiling upon changes, which meant that a developer would have to manually call the compileLess task from the terminal every time they wanted to see a style change appear in the browser. This added minutes to the development workflow and cut into the developer’s feedback loop. As weeks turn into months, the context switching and idle time adds up and becomes costly for the developer, their team, and employer.

With the topic front-of-mind, and my frustration simmering, I decided to find a fix. Enter the VS Code debugger….

Setup

To begin with Visual Studio Code’s built in debugger, select the bug symbol in the left side bar and click on the settings cog to access debugger configurations. Alternatively, you can get here in the Debug -> Open Configurations top menu. Debugger configurations are stored in JSON format at the root level of your project in the VS Code workspace directory. More specifically, you can find it at <app-root>/.vscode/launch.json.

Setup your launch.json to begin debugging with VS Code

Once here, you may find some preset configurations, but we’ll want to add our own. Select the Add Configuration… button in the bottom right corner of the launch.json window and IntelliSense will provide options to add a launch configuration snippet. For a comprehensive list of launch configuration attributes and common snippets, head here.

Gulp

In the example above, I am demonstrating setup to debug a specific gulp task titled watchLess. Upon clicking the Add Configuration… button, we are presented with options to add some boilerplate. I select the Node.js: Gulp task option and customize it for the watchLess task.

Once I’ve saved the configuration file, you will notice that the new debug option we added can now be selected in the drop-down at the top of the debugger pane. Note that the name property of the configuration object determines how the task will appear in the debugger drop down.

Toggle breakpoints by clicking on the editor margin. Right-click to add conditional breakpoints

From here we can set a breakpoint. Previous investigation had shown that the bug was likely coming from the task’s handleIncludeCompile function, but I needed help confirming that hunch. In the above gif you can see as I place a breakpoint within the function in its respective file.

After the breakpoint is set, we can start debugging by pressing F5 or by clicking the green start button. The gulp task is now running and sure enough, the debugger stops at our breakpoint after a change is made to a random *.less file. Once we hit the breakpoint, we can resume code execution F5, step over F10, into F11, or out Shift + F11 of a function.

When the debugger stops at the breakpoint in the screenshot below, we’re able to see a great deal more information than was afforded to us with simple logging statements. In the left hand pane we can inspect the code’s variables and their data at a given point of execution. We’re also able to hover over previously executed code to see variable values.

As it turns out, the src paths that were passed in the config object had outdated glob patterns and no longer worked with our updated build structure, hence the reason the watch task wasn’t properly recompiling.

The data provided in the left hand panel of the debugger helped to identify an outdated glob pattern in the src path

Don’t worry if the example doesn’t quite make sense, just know that the debugger enabled us to pause the gulp task and view data at a given point in time, thereby helping us identify and squash the bug.

Browser

As someone who’s accustomed to debugging in Chome’s devtools, I was doubtful that a VS Code extension would make a difference. That was until I read this terrific post from Kenneth Auchenberg on the popular Debugger for Chrome extension. The extension allows the use of the VS Code debugger in lieu of the browser’s dev tools, allowing a developer to eliminate a step from a standard debugging workflow.

To get started, download the Debugger for Chrome extension. You will find beginning steps for some popular frameworks/libraries below.

Speed up your debugging skills

React

  1. Create a React app using create-react-app
  2. Open your project’s launch.json and add the following configuration

3. Start your React app by running npm start or yarn run start in the terminal

4. Begin debugging in VS Code by setting a breakpoint and pressing F5

Angular

  1. Create Angular app using Angular CLI
  2. Make sure Chrome is version 59 or greater (see issue)
  3. Open your project’s launch.json and add the following configuration

4. Start your Angular app by running ng serve in the terminal

5. Begin debugging in VS Code by setting a breakpoint and pressingF5

Vue

  1. Create Vue app using vue-cli
  2. Open your project’s launch.json and add the following configuration

4. Start your Vue app by running npm run dev in the terminal

5. Begin debugging in VS Code by setting a breakpoint and pressingF5

Attaching to Chrome

To attach to Chrome as opposed to launching a new window, use the "request": "attach" config option. Before attaching you will need to launch Chrome with remote debugging enabled.

Windows

  • Right click the Chrome shortcut, and select properties
  • In the “target” field, append --remote-debugging-port=9222
  • Or in a command prompt, execute <path to chrome>/chrome.exe --remote-debugging-port=9222

macOS

  • In a terminal, execute /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222

Linux

  • In a terminal, launch google-chrome --remote-debugging-port=9222
Example “Attach” config

A Quick Note on Source Maps

The Debugger for Chrome extension uses source maps to let you debug your original sources, but you may find yourself in a situation where source maps aren’t generated properly and overrides are needed. In the launch config you can set overrides by using the sourceMapPathOverrides option. This is useful when the source map isn’t accurate or can’t be fixed in the build process.

More information on source maps in Debugger for Chrome can be found here.


Extensions

You can find various extensions in the VS Code marketplace that will add debugging support for the language of your choice (C#, Ruby, Python, and more).

Below I will highlight extensions that go beyond traditional language support and offer some notable functionality.

  • Quokka: Per the website, Quokka is a prototyping playground for JavaScript and TypeScript. It runs your code immediately as you type and displays various execution results in your code editor. I haven’t had much experience with this one at work, but I’ve played around with a bit and have found it to be an interesting learning tool.

Tips

  • Pause on Exception: by default, the debugger automatically pauses code on exception. To disable this, see the Deactivate Breakpoints toggle button seen in the screenshot below. You can also quickly remove all breakpoints from this menu.
Options to Add Function Breakpoint, Deactivate Breakpoints, and Remove All Breakpoints
  • Skip Files: If you need to ignore/blackbox files to eliminate noise in the stacktrace, you can use skipFiles option for configurations utilizing the Debugger for Chrome extension. For example:
"skipFiles": ["angular.js"]

Conclusion

I want to extend a massive 👍 to VS Code. Check out VS Code if you haven’t already, and don’t repeat my mistake of waiting to utilize the editor’s debugger. It’s a powerful utility that has markedly improved my day to day workflow.

I look forward to adding more tips and tricks here as I find them. Feel free to comment with your own below!

Thanks 🙌

Special thanks to Will Beard for recommending I finally check out the debugger for Node debugging and also to the VS Code team for their excellent work. I’ve found them to be very responsive with issues and Kenneth Auchenberg has many insightful posts on this topic and more.

If you found this post helpful, please let me know by clicking 👏 below!

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.