Debugging Node.js Like a Pro
Most Node.js debugging happens with console.log . That works until it doesn't: async stacks that point to the wrong place, a variable that changes between the log and the crash, or a server that only misbehaves on one request out of a thousand. Here's the toolkit I reach for instead. Start with --inspect , not print statements The built-in inspector gives you breakpoints, step-through, and a real…
Debugging Node.js primarily involves using console.log, but this method becomes less effective when dealing with complex issues such as asynchronous stacks, variable inconsistencies, or sporadic server malfunctions. Instead, consider employing the following strategies from the author's toolkit. Begin by incorporating the built-in inspector by running your process like so: node --inspect app.js.
Subsequently, open Chrome and navigate to chrome://inspect, then click "inspect". For processes that are difficult to restart (like workers or Docker containers), use --inspect-brk to halt execution at the initial line, or send SIGUSR1 to an already running process to enable the inspector temporarily. If you need to access the inspector from outside a Docker container, explicitly bind it using node --inspect=0.0.0.0:9229 app.js. Remember not to expose this on a public host.
To pinpoint issues within loops, right-click the line in DevTools and add a conditional breakpoint. Instead of having a breakpoint that triggers every iteration, like for ( const order of orders ) { processOrder ( order ); // stops 10,000 times }, set the condition to order.id === abc123 and it will halt precisely once. This technique transforms irregular bugs into reproducible scenarios.
Utilize debugger; statements judiciously, as they function as breakpoints when the inspector is attached and are ignored otherwise. This approach allows you to safely embed temporary debugging code within your application. When logging, prefer console.dir(obj, { depth: null }); over console.log(user: , user) as it handles deeply nested data and circular references more effectively.
For asynchronous code, enable --async-stack-traces (available by default in recent Node versions) to view a complete error stack, rather than one that starts at the callback function. If your application is slow rather than broken, breakpoints offer little assistance. Instead, use the built-in profiler by running node --cpu-prof --cpu-prof-dir = ./profiles app.js.
This generates a .cpuprofile file that can be analyzed in Chrome DevTools under the Performance tab. Look for wide bars indicating functions that consume significant time. For memory issues, use --heap-prof to generate allocation profiles and process.memoryUsage() to obtain a snapshot of current memory usage: setInterval (() = { const { heapUsed } = process . memoryUsage (); console . log ( `heap: ${( heapUsed / 1024 / 1024 ). toFixed ( 1 )} MB` ); }, 5000 ); A steadily increasing heap without drops suggests a memory leak, while a sawtooth pattern indicates normal garbage collection.
Always review the entire error object, including err.code, to gain insights into the nature of the failure. Log the complete error object, not just err.message.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.