Developer workflow for debugging plugins

I've set up Node-RED with this flag:
--userDir 'C:\Users\mbramer\Documents\NodeRED\config'

I'm looking to hit debug breakpoints within plugin code, so I can dev. I did an npm install '<local_file_path>' in the directory: C:\Users\mbramer\Documents\NodeRED\config but the plugin isn't showing up. The local_file_path is a git clone of a plugin that works and I'm already using. What's the recommended way of developing plugins, as I seem to be missing something? Also, is there a way to hot-reload plugins without restarting Node-RED?

Edit: I've got the plugin showing up now, but not able to hit a breakpoint. I'm using VSCode, but also used Visual Studio to attach to the node process, but it's not hitting a breakpoint. The package.json looks good too and the dependency is installed and in the node_modules folder.

Check the package.json file in your userDir, it should show your locally installed nodes. For example, on my dev PC, I have:

    "dependencies": {
        "node-red-contrib-cron-plus": "*",
        "node-red-contrib-fs": "file:../../node-red-contrib-fs",
        "node-red-contrib-moment": "file:../../node-red-contrib-moment",
        "node-red-contrib-nbrowser": "~1.1.4",
        "node-red-contrib-static-markdown": "file:../../node-red-contrib-static-markdown",
        "node-red-contrib-telegrambot": "^6.0.1",
        "node-red-contrib-telegrambot-home": "*",
        "node-red-contrib-ui-led": "*",
        "node-red-contrib-ui-svg": "*",
        "node-red-contrib-uibuilder": "file:../../node-red-contrib-uibuilder",
        "node-red-dashboard": "*",
        "node-red-node-data-generator": "*",
        "node-red-node-google": "*",
        "normalize.css": "*",
        "nr-test": "file:../../nr-test",
        "uibuilder-vuejs-component-extras": "file:../../uibuilder-vuejs-component-extras",
    },

There's some other stuff in there but that's the bulk. You can see the local ones because they use "file:" references.

Nope. The nodes are only loaded on startup.

Instead use a wrapper like PM2 or nodemon with a configuration setting to restart Node-RED when any of the node files change.

I use nodemon with the following in my master package.json file:

  "scripts": {
    "start": "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",
    "admin": "node node_modules/node-red-admin/node-red-admin.js",
    "restart": "sudo systemctl restart node-red",
    "restartnr": "node ./bin/restartnr.js one -aaa two --bb--bb three -cc-cc four five",
    "log": "sudo journalctl -u node-red -f -n 0 -o cat",
    "update": "npm install --unsafe-perm --production node-red",
    "check": "npm outdated",
    "check-data": "cd data && npm outdated",
    "update-data": "cd data && npm update",
    "check-master": "npm outdated",
    "update-master": "npm update",
    "adminui": "start http://localhost:1880/red/",
    "ui": "start http://localhost:1880/ui/"
  },
  "nodemonConfig": {
    "ignore": [
      ".vscode",
      "/src/node-red-contrib-uibuilder/nodes/dist",
      "/src/node-red-contrib-uibuilder/nodes/icons",
      "/src/node-red-contrib-uibuilder/nodes/src",
      "/src/node-red-contrib-uibuilder/nodes/templates",
      "/src/node-red-contrib-uibuilder/node-src",
      "/src/node-red-contrib-static-markdown1/node-admin-src"
    ],
    "watch": [
      "/src/node-red-contrib-static-markdown1/nodes/",
      "/src/node-red-contrib-static-markdown1/",
      "/src/node-red-contrib-uibuilder/nodes/",
      "/src/nr-test/nodes/"
    ],
    "env": {
      "NODE_ENV": "development"
    }
  },
1 Like

How do you hit a breakpoint on the plugin code? I'm using VSCode, but am flexible on tooling. I am able to hit a breakpoint on red.js

In VScode, you can simply click in the left margin on any line of code to set a break. You can also use the standard Javascript debugger statement to break the code dynamically.

If using a Chromium browser for remote debugging, you can click in the left margin of the code in the browser.

Are you using VSCode for debugging? I have a simple launch.json

{
  // Use IntelliSense to learn about possible attributes.
  // Hover to view descriptions of existing attributes.
  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Launch Program",
      "program": "${workspaceFolder}\\node_modules\\node-red\\red.js",
      "args": [
        "--port",
        "1881",
        "--userDir",
        "C:\\Users\\mbramer\\Documents\\Node-RED-DEV\\config"
      ],
      "skipFiles": ["<node_internals>/**"]
    }
  ]
}

But am not able to hit a breakpoint in the plugin code. I am able to hit one in red.js though. Here's the package.json in the config directory:

{
    "name": "node-red-project",
    "description": "A Node-RED Project",
    "version": "0.0.1",
    "private": true,
    "dependencies": {
        "node-red-contrib-aws-sdk-anything": "file:../../../Github/node-red-contrib-aws-sdk-anything"
    }
}

The plugin does load in the UI, so I know it's picking up the dependency. The breakpoint isn't bound for some reason.

Untitled

Thanks for your help @TotallyInformation! I think I know what I need to do now. It's a tad bit different than the workflow I'm used to, but essentially, I'll need to start the process in another shell, then attach via VSCode. There is a way to get all of that to occur from launch.json, so I'm going to work on that and get it sorted.

Thanks again!

Add a debug script to package.json in the node-red installation directory.

{
  "name": "node-red-dev",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "debug": "node.exe --inspect-brk .\\node_modules\\node-red\\red.js --port 1881 --userDir C:\\Users\\mbramer\\Documents\\node-red-dev\\config",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "node-red": "^1.0.3"
  }
}

Then in the launch.json add this:

{
  // Use IntelliSense to learn about possible attributes.
  // Hover to view descriptions of existing attributes.
  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Launch via NPM",
      "type": "node",
      "request": "launch",
      "cwd": "${workspaceRoot}",
      "runtimeExecutable": "npm",
      "runtimeArgs": ["run", "debug"],
      "port": 9229
    }
  ]
}

Before you start debugging, I've found you have to add your breakpoints first from the debug panel.

Here is my VScode launch.json file that controls the debug process:

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "type": "node",
            "request": "attach",
            "name": "Attach by Process ID",
            "processId": "${command:PickProcess}"
        },
        {
            "type": "node",
            "request": "launch",
            "name": "Launch Program",
            "program": "${workspaceFolder}\\node_modules\\node-red\\red.js"
        }
    ]
}

Then I can simply run npm run inspect from the VScode terminal and everything automatically connects.

Before starting with inspect, open a file that you want to debug and set a breakpoint in it. When you then start node-red, it will break at that point. I also turn on "Uncaught Exceptions".

I don't recommend turning on "All Exceptions" since you will be all day trying to get Node-RED to move to something useful.

1 Like