Hi folks,
I developed a long time ago the node-red-contrib-msg-speed node. But I need to develop another node, which needs the reuse most of the internals as the speed node. I would like to share the functionality between both nodes, to avoid having to maintain it twice...
What is the best way to deal which such a situation:
- Extract that functionality from the speed node and isolate it into a new separate npm package (and let both nodes use that package as a dependency).
- Other solutions?
Thanks!
Bart
Hi Bart,
Publish the "speed code" as an NPM package and include it in your 2 other projects. NPM will deduplicate under the hood.
Thanks Steve!
And do you have any good practices for such a common NPM package?
My simplified speed-node package contains this:
module.exports = function(RED) {
"use strict";
var CircularBuffer = require("circular-buffer");
var Math = require("mathjs");
function speed(config) {
RED.nodes.createNode(this, config);
// Initialization code
this.on("input", function(msg) {
// Message handling code
});
this.on("close",function() {
// Cleanup code
});
}
RED.nodes.registerType("msg-speed", speed);
};
Do you have any advise on how such a common NPM package could look like (and how I can call it both my nodes)?
Because most of the code in the 3 code blocks would be common for both nodes, but each node also needs to execute some dedicated code in each block ...
So which bit is common ? Just the requires ? If so I wouldn’t worry. Just duplicate it and let npm take care of it.
In fact I mean that every of the 3 blocks (initialization, message handling, cleanup) contain shared code, which should be part of the common npm package. But my both nodes - which depend on this package - should be able to execute their own code in each block.
Probably there is a very simple solution, but I don't see it at the moment ...
Well if they are related functions (ie also to do with speed) - such that you would ship them both as one package then you can define them both in the same files. If not then not easily no.
I have now extracted the core functionality from the node-red-contrib-msg-speed, and moved it to a new nr-msg-statistics package.
For anybody who needs to do something similar in the future, below you can find how I did it. Although there might be many ways to get to Rome ... But since I have a background as object oriented developer, I really wanted to use ES6 classes to accomplish this. So no callback functions for me this time 
-
In the new Github repository, I encapsulated all the shared functionality into a class (which will be exported):
module.exports = class MessageAnalyzer {
constructor (config) {
// Do some initialization, and store the Node-RED node config into this instance
this.someProperty = config.someProperty;
...
}
someMethod(someParameter) {
...
this.doSomething();
...
this.doSomethingElse();
...
};
doSomething() {
}
doSomethingElse() {
}
}
-
The someMethod contains my old logic (of the speed node), which I want to reuse in other nodes.
But at some points in the code I call the (e.g. empty) methods doSomething and doSomethingElse.
-
I added the new npm package as a dependency in the package.json file of my speed node:
"dependencies": {
"nr-msg-statistics": "^1.0.0"
},
-
The speed node now imports this class, and creates a subclass of it. That subclass will override the methods doSomething and doSomethingElse to do stuff that is specific to this speed node:
module.exports = function(RED) {
function speedNode(config) {
RED.nodes.createNode(this, config);
var node = this;
const MessageAnalyzer = require('nr-msg-statistics');
class MessageSpeedAnalyzer extends MessageAnalyzer {
doSomething() {
// Do some speed related stuff
}
doSomethingElse() {
// Do some other speed related stuff
}
}
// Create an intance of the subclass
var messageSpeedAnalyzer = new MessageSpeedAnalyzer(config);
// By calling this method, underneath the doSomething and doSomethingElse will be called.
messageSpeedAnalyzer.someMethod(...);
}
}
So I can reuse the code (in the MessageAnalyzer class) to share it between multiple Node-RED nodes, and each node can overwrite the methods to do stuff that is specific to that node ...
Damn it was fun working with classes after a long time 