A few articles have been written about debugging with Node-RED, I think there is one on my blog.
Most of the time, debugging involves simply copious amounts of logging statements. I tend to use console.log for temporary outputs - leaving the node-red log for things I probably want to leave in place longer-term.
I also tend to include some standard info about where in my node the output is coming from. Such as this simple example from uibuilder:
console.log('[uiblogin] Validation Errors: ', errors)
or this slightly more complex example:
console.log('[uibuilder:socket.on.control] Use Security _auth: ', msg._auth, `. Node ID: ${node.id}`)
For the occasional need that goes beyond that, I use VScode's debugging features by starting up Node-RED with a custom npm start script:
"scripts": {
"start": "pm2 start ecosystem.config.js",
"start4": "nodemon --ext js,html node_modules/node-red/red.js --userDir ./data",
"start2": "set DEBUG=express:* & nodemon node_modules/node-red/red.js --userDir ./data",
"start3": "node node_modules/node-red/red.js --userDir ./data",
"doctor": "clinic doctor -- node node_modules/node-red/red.js --userDir ./data",
"bubble": "clinic bubbleprof -- node node_modules/node-red/red.js --userDir ./data",
"inspect": "node --inspect node_modules/node-red/red.js --userDir ./data",
The last one attaches an inspector which can be used from within VScode. You need to remember to put a break statement in your code though otherwise the way that Node-RED starts up, you wont see much in the debugger.
Node.js isn't that easy to debug itself and the complexity of Node-RED as a platform makes that even harder because of the way everything links together. But once you have the hang of it, it isn't too hard.