Flash cards
Review the key moves
What is the main idea behind Node.js Advanced Debugging?
Lesson checks
Practice each idea before moving on
Short Mimo-style checks built from this lesson's code, terms, and sequence.
Which statement best captures the main point of this lesson?
Complete the missing token from the example code.
___ --inspect app.jsPut the learning moves in the order that makes the concept easiest to apply.
Introduction to Advanced Debugging
Effective debugging is a critical skill for Node.js developers.
While console.log() is useful for basic debugging, advanced techniques allow you to diagnose complex issues like memory leaks, performance bottlenecks, and race conditions.
This tutorial covers advanced debugging techniques and tools to help you solve challenging problems in your Node.js applications.
Advanced debugging tools provide capabilities like
- Setting breakpoints and stepping through code execution
- Inspecting variable values at runtime
- Visualizing memory consumption and finding leaks
- Profiling CPU usage to identify performance bottlenecks
- Analyzing asynchronous call stacks
Debugging with Chrome DevTools
Node.js includes built-in support for the Chrome DevTools debugging protocol, allowing you to use the powerful Chrome DevTools interface to debug your Node.js applications.
Starting Node.js in Debug Mode
There are several ways to start your application in debug mode:
Standard Debug Mode
node --inspect app.jsThis starts your app normally but enables the inspector on port 9229.
Break on Start
node --inspect-brk app.jsThis pauses execution at the first line of code, allowing you to set up breakpoints before execution begins.
Custom Port
node --inspect=127.0.0.1:9222 app.jsThis uses a custom port for the inspector.
Connecting to the Debugger
After starting your Node.js application with the inspect flag, you can connect to it in several ways:
- Chrome DevTools: Open Chrome and navigate to chrome://inspect . You should see your Node.js application listed under "Remote Target." Click "inspect" to open DevTools connected to your application:
- DevTools URL: Open the URL shown in the terminal (usually something like devtools://devtools/bundled/js_app.html?experiments=true&v8only=true&ws=127.0.0.1:9229/... ).
Using DevTools for Debugging
Once connected, you can use the full power of Chrome DevTools:
- Sources Panel: Set breakpoints, step through code, and watch variables
- Call Stack: View the current execution stack, including async call chains
- Scope Variables: Inspect local and global variables at each breakpoint
- Console: Evaluate expressions in the current context
- Memory Panel: Take heap snapshots and analyze memory usage
Pro Tip: Use the Sources panel's "Pause on caught exceptions" feature (the pause button with curved lines) to automatically break when an error occurs.
Debugging in VS Code
Visual Studio Code provides excellent built-in debugging capabilities for Node.js applications.
Setting Up Node.js Debugging in VS Code
You can start debugging your Node.js application in VS Code in several ways:
- launch.json Configuration: Create a .vscode/launch.json file to define how VS Code should launch or attach to your application.
- Auto-Attach: Enable auto-attach in VS Code settings to automatically debug any Node.js process started with the --inspect flag.
- JavaScript Debug Terminal: Use the JavaScript Debug Terminal in VS Code to automatically debug any Node.js process started from that terminal.
Example launch.json Configuration
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${workspaceFolder}/app.js",
"skipFiles": ["<node_internals>/**"]
},
{
"type": "node",
"request": "attach",
"name": "Attach to Process",
"port": 9229
}
]
}VS Code Debugging Features
VS Code provides powerful debugging capabilities
- Breakpoints: Set, disable, and enable breakpoints by clicking in the gutter of your code editor.
- Conditional Breakpoints: Right-click on a breakpoint to set a condition that must be true for the breakpoint to trigger.
- Logpoints: Add logging without modifying code by setting logpoints that print messages to the console when hit.
- Watch Expressions: Monitor the value of variables and expressions as you step through code.
- Call Stack: View and navigate the call stack, including asynchronous frames.
Note
VS Code can also debug TypeScript files directly, with source maps enabling debugging of the original TypeScript code rather than the transpiled JavaScript.
Using the Debug Module
The debug module is a lightweight debugging utility that allows you to add conditional logging to your Node.js applications without cluttering your code with console.log statements.
Installing the Debug Module
npm install debugBasic Usage of Debug
The debug module lets you create namespaced debug functions that can be enabled or disabled via environment variables:
Example: Using the Debug Module
// Create namespaced debuggers for different parts of your application
const debug = require('debug');
const debugServer = debug('app:server');
const debugDatabase = debug('app:database');
const debugAuth = debug('app:auth');
// Use the debuggers in your code
debugServer('Server starting on port %d', 8080);
debugDatabase('Connected to database: %s', 'mongodb://localhost');
debugAuth('User %s authenticated', 'john@example.com');
// By default, these debug messages won't appear in the outputEnabling Debug Output
To see the debug output, set the DEBUG environment variable to a comma-separated list of namespace patterns:
Enable All Debug Output
DEBUG=app:* node app.jsEnable Specific Namespaces
DEBUG=app:server,app:auth node app.jsEnable All but Exclude Some
DEBUG=app:*,-app:database node app.jsDebug Output Features
- Each namespace has a unique color for easy visual identification
- Timestamps show when each message was logged
- Supports formatted output similar to console.log
- Shows the difference in milliseconds from the previous log of the same namespace
Best Practice: Use specific namespaces for different components of your application to make it easier to filter debug output based on what you're currently troubleshooting.
Finding and Fixing Memory Leaks
Memory leaks in Node.js applications can cause performance degradation and eventual crashes.
Detecting and fixing memory leaks is a crucial debugging skill.
Common Causes of Memory Leaks in Node.js
- Global Variables: Objects stored in global scope that are never cleaned up
- Closures: Functions that maintain references to large objects or variables
- Event Listeners: Listeners that are added but never removed
- Caches: In-memory caches that grow without bounds
- Timers: Timers (setTimeout/setInterval) that aren't cleared
- Promises: Unhandled promises or promise chains that never resolve
Detecting Memory Leaks
Several approaches can help you detect memory leaks:
// Monitor memory usage
function logMemoryUsage() {
const memoryUsage = process.memoryUsage();
console.log('Memory usage:');
console.log(`RSS: ${Math.round(memoryUsage.rss / 1024 / 1024)} MB`);
console.log(`Heap Total: ${Math.round(memoryUsage.heapTotal / 1024 / 1024)} MB`);
console.log(`Heap Used: ${Math.round(memoryUsage.heapUsed / 1024 / 1024)} MB`);
}
// Log memory usage every 30 seconds
setInterval(logMemoryUsage, 30000);Heap snapshots provide a detailed view of memory allocation:
- Start your app with node --inspect app.js
- Connect with Chrome DevTools
- Go to the Memory tab
- Take heap snapshots at different points
- Compare snapshots to find objects that are growing in number or size
- clinic doctor : Identify memory issues in your application
- clinic heap : Visualize heap memory usage
- memwatch-next : Library to detect memory leaks