Embed node-red *and* custom nodes in existing app?

TLDR Summary: When embedding node-red in an existing app, I'm hoping there's a way to "require" the app's modules from the .js files of custom nodes that I write.

Details:
I have an existing node.js express app (serving some JSON rest apis).

I successfully embedded node-red into that app following the docs here:
https://nodered.org/docs/user-guide/runtime/embedding

And I've successfully created a standalone custom node, i.e. with it's own package.json in the form that could be published all by itself which I assume is the normal way.

But my node app has business logic in modules that I need to require and use from the js file for a suite of custom nodes that would be specific to my project.

But those modules aren't separately published they're just under src of the node app.

And so I can't do "requires" for that code from a custom node coded the typical way as a separate standalone package right?

My question: now that I've embedded node-red in this app, can I create my custom nodes simply as files under the src of the app's package instead of being separate standalone packages?

And doing that would it mean the js files for those custom nodes would be able to do requires of my "business logic" modules there?

Update:

I've figured out something that works which is:
a. In my main file where I embed node-red I point userDir at my project root directory i.e.:

  const settings = {
    // we are pointing userDir at our project root so that our custom nodes
    // can see the same node_modules as our project
    userDir: `${console.log(__dirname)}/..`,
...
  }

b. I add all the node-red node dependencies that were in ~/node-red/package.json into my project's package.json.

c. I put my custom nodes as loose js/html files in the "nodes" directory (which is simply under the project root directory because of a)

Now my only concern is about "c" from the node-red docs about the "nodes" directory:
https://nodered.org/docs/user-guide/runtime/adding-nodes#installing-individual-node-files

It says "this is only recommended for development purposes".

Does anybody know why it's only recommended for development?
Is it like a security risk somehow?
(or maybe it's just there's no easy way to publish and share custom nodes that way - in that case maybe I'm ok as I don't/can't share my custom nodes they are specific to my project)

Here's how I do it ....
I have a main .js file that loads node-red using most of the stuff/technique in the link you mentioned ...
it's in a main directory with all the usual "node-modules" (incl. NR)

The other .js file of my app are in a specific sub-directory.

From the main .js file I require other .js files (that are part of my mixed-NR app) just the normal way (pointing to sub-dir)...

My custom nodes are in a "local-modules" folder under that sub-dir ... the package.json file (in the sub-dir) includes those dependencies as "file:" (ex: "node-red-contrib-xxx": "file:local-modules/node-red-contrib-xxx") mostly because they're not available on npm or anywhere on the net ...

Thanks tilleul glad to hear from someone doing this I'm pretty new to node-red...

Read your post several times but I'm not 100% sure I'm following.

You couldn't easily show your dir structure here could you? maybe with a screen grab or e.g. on mac with "tree": https://rschu.me/list-a-directory-with-tree-command-on-mac-os-x-3b2d4c4a4827

If not could you clarify: do you have multiple package.json files and multiple node_modules directories? i.e. separate for your app versus for your custom nodes?

I'm esp. curious because: in one of the things I tried (that I thought seemed similar to what you described) I found I was able to require simple modules from the app's code, but if those modules did requires of npm installed node_modules modules things didn't work. That's what I thought got fixed by my current approach having exactly one node_modules dir for both the app and the custom nodes.

You should still create your nodes as proper packages as though you were going to publish via npm. You can then "install" them locally and you will see the entry that npm creates in package.json. The install command becomes npm install /path/to/code. You can install node packages either in your app's root folder or in your userDir folder, either will work.

Having done that, you can require your packages in the normal way. Just make sure that, if you are backing-up/distributing your app, you include the relevant parts of the source folders.

Really though, you could avoid all of the messing by publishing your packages or even by using private GitHub repositories if the code shouldn't be public. This will make it much easier to manage.

don't forget npm pack will create a local tgz file of the complete node that can be installed, so you can "freeze" your extra nodes and just install them as required.

2 Likes

Thanks Totallyinformation I tried what you said the approach of just npm install'ing my custom node package directly as a dependency of my app project (i.e. so it winds up under my app's node_modules).

I thought I was having trouble again doing requires from the custom node's javascript up to the modules under the app's src dir.

Until I realized npm install /path/to/code approach makes a sym link under node_modules that was the only reason my require('../../src/appmodule') paths weren't happy. When I removed the symlink and copied the package directly it worked fine.

Anyway thanks glad to get more clarity around this!!

Re your other comments I've decided I really am in development/"proof of concept" mode (just trying to get something together hoping to convince my coworkers about node-red, i.e. the coworkers who work on this app I've embedded node-red into).

So for now I'm going to use the "nodes" dir approach (to keep things simple and require minimal changes of the main app for now), but for production yeah I follow I should get the code these custom nodes use into separate packages the app would also be using. Makes sense.

Structure is as follows:

  • node-modules (includes NR and its dependencies but also NodeJS modules my app needs -- created/managed by npm)
  • main.js (this .js file will create a NR server as explained in the docs and require
    app/apps.js)
  • package.json (this file is built by npm)
  • app (this folder is the main folder for my app)
    • app.js (main .js file, a standard NodeJS app)
    • local-modules (this folder contains my custom non-public NR nodes)
    • package.json (this is the package.json file for my app - managed by npm)
    • node-modules (this folder contains symlinks to local-modules -- created by npm i -- as it turns out NR contrib-nodes are installed here as well by the palette manager)
    • (the rest of the structure is really my NodeJS app)

Hope this helps :slight_smile: