Subflows can be packaged as npm modules and distributed like any other node.
When they are installed, they will appear in the palette as regular nodes. Users are not able to see or modify the flow inside the subflow.
At this stage, creating Subflow module is a manual process that requires hand-editing the Subflow JSON. We will provide tooling in the future to help automate this - but for now, these instructions should help you get started.
Any subflow can be packaged as a module. Before you do so, you need to think about how it will be used. The following checklist is a useful reminder of the things to consider:
The Subflow can hold additional metadata that can be used to define the module it will be packaged in.
On the Subflow Module Properties edit dialog you can set the following properties:
Module
- the npm package nameNode Type
- this will default to the id
property of the subflow. It is helpful to provide a better type value. As with regular node types, it must be unique to avoid conflicts with other nodes.Version
Description
License
Author
Keywords
This is where the manual work outside of Node-RED comes in.
create a directory with the name you want to give the module. For this example, we’ll use node-red-example-subflow
.
mkdir node-red-example-subflow cd node-red-example-subflow
Use npm init
to create a package.json
file:
npm init
It will ask a series of questions - provide matching answers to the values you added to the subflow metadata.
Add a README.md
file - as all good modules must have a README.
Create a JavaScript wrapper for your module. For this example, we’ll use example.js
:
const fs = require("fs");
const path = require("path");
module.exports = function(RED) {
const subflowFile = path.join(__dirname,"subflow.json");
const subflowContents = fs.readFileSync(subflowFile);
const subflowJSON = JSON.parse(subflowContents);
RED.nodes.registerSubflow(subflowJSON);
}
This reads the contents of a file called subflow.json
- which we’ll create in a moment - parses it and then passes it to the RED.nodes.registerSubflow
function.
With all of that in place, you can now add your subflow to the module. This requires some careful editing of the subflow json.
Ctrl-E
or Menu->Export
) and paste the JSON into a text editor. The next steps will be easier if you select the ‘formatted’ option on the JSON tab of the Export dialog.The JSON is structured as an Array of Node objects. The last-but-one entry is the Subflow Definition and the last entry is the Subflow Instance you added to the workspace.
[
{ "id": "Node 1", ... },
{ "id": "Node 2", ... },
...
{ "id": "Node n", ... },
{ "id": "Subflow Definition Node", ... },
{ "id": "Subflow Instance Node", ... }
]
[
of the Array"flow"
.subflow.json
{
"id": "Subflow Definition Node",
...
"flow": [
{ "id": "Node 1", ... },
{ "id": "Node 2", ... },
...
{ "id": "Node n", ... }
]
}
The final task is to update your package.json
so that Node-RED knows what your module contains.
Add a "node-red"
section, with a "nodes"
section containing an entry for your .js
file:
{
"name": "node-red-example-subflow",
...
"node-red": {
"nodes": {
"example-node": "example.js"
}
}
}
If your subflow uses any non-default nodes, you must make sure your package.json
file lists
them as dependencies. This will ensure they will get installed alongside your module.
The modules are listed in the standard top-level "dependencies"
section and a "dependencies"
section in the "node-red"
section.
{
"name": "node-red-example-subflow",
...
"node-red": {
"nodes": {
"example-node": "example.js"
},
"dependencies": [
"node-red-node-random"
]
},
"dependencies": {
"node-red-node-random": "1.2.3"
}
}
Node-RED: Low-code programming for event-driven applications.
Copyright OpenJS Foundation and Node-RED contributors. All rights reserved. The OpenJS Foundation has registered trademarks and uses trademarks. For a list of trademarks of the OpenJS Foundation, please see our Trademark Policy and Trademark List. Trademarks and logos not indicated on the list of OpenJS Foundation trademarks are trademarks™ or registered® trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.
The OpenJS Foundation | Terms of Use | Privacy Policy | OpenJS Foundation Bylaws | Trademark Policy | Trademark List | Cookie Policy