'require' not defined?

Need help with using a module like 'moment' which fails with my setup.
This is the code added to a function node:

const moment = require('moment');
const now = moment();
// Format the timestamp
msg.payload = now.format('YYYY-MM-DD HH:mm:ss');

It results with an error:
ReferenceError: ReferenceError: require is not defined (line 21, col 16) see more details below

I found functionExternalModules needs to be enabled in settings.js, it needs to restart NR. All done, no change --> Error
I run 'moment' directly from CLI, all good.
No further ideas here! What could be the problem?


(Node : v20.18.1 / npm : 10.8.2)

ReferenceError: require is not defined
    at Function node:b54bf4877315a563 [open3e/ecu  LISTEN  --> FLOW]:22:16
    at Function node:b54bf4877315a563 [open3e/ecu  LISTEN  --> FLOW]:106:3
    at Script.runInContext (node:vm:149:12)
    at processMessage (/usr/lib/node_modules/node-red/node_modules/@node-red/nodes/core/function/10-function.js:419:33)
    at FunctionNode._inputCallback (/usr/lib/node_modules/node-red/node_modules/@node-red/nodes/core/function/10-function.js:342:17)
    at /usr/lib/node_modules/node-red/node_modules/@node-red/runtime/lib/nodes/Node.js:214:26
    at Object.trigger (/usr/lib/node_modules/node-red/node_modules/@node-red/util/lib/hooks.js:166:13)
    at Node._emitInput (/usr/lib/node_modules/node-red/node_modules/@node-red/runtime/lib/nodes/Node.js:206:11)
    at Node.emit (/usr/lib/node_modules/node-red/node_modules/@node-red/runtime/lib/nodes/Node.js:190:25)
    at Node.receive (/usr/lib/node_modules/node-red/node_modules/@node-red/runtime/lib/nodes/Node.js:499:10)
16 Jan 19:50:21 - [error] [function:open3e/ecu  LISTEN  --> FLOW] ReferenceError: ReferenceError: require is not defined (line 21, col 16)

you cant use require in a Function
you have to go in the Setup tab of the Function node to load the module.

and actually it auto-installs .. no need to manually install the module

Then you can use it with whatever name you gave it in the Import as section

Test Flow

[{"id":"da4e78e477349636","type":"function","z":"54efb553244c241f","name":"use moment","func":"msg.payload = moment().format(\"DD MMM YYYY HH:mm\")\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"moment","module":"moment"}],"x":390,"y":3180,"wires":[["afb950181a147d88"]]},{"id":"cc02d872c7c5b82d","type":"inject","z":"54efb553244c241f","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":200,"y":3180,"wires":[["da4e78e477349636"]]},{"id":"afb950181a147d88","type":"debug","z":"54efb553244c241f","name":"debug 12","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":550,"y":3180,"wires":[]}]
1 Like

Or just use a change node :smiley:
no need to install moment - its built into the change node

[{"id":"8bab5339272e69b1","type":"change","z":"2d7bf6e3.84c97a","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"$moment().tz('Europe/London').format('YYYY-MM-DD HH:mm:ss')","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":480,"y":1540,"wires":[["7d690285bb0b77aa"]]},{"id":"d828b59fc710a363","type":"inject","z":"2d7bf6e3.84c97a","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":280,"y":1540,"wires":[["8bab5339272e69b1"]]},{"id":"7d690285bb0b77aa","type":"debug","z":"2d7bf6e3.84c97a","name":"debug 389","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":690,"y":1540,"wires":[]}]

There's also a guide & video which should help you - https://flowfuse.com/blog/2023/06/import-modules/

This brings me to the following question:
Could javascript scripts that are needed at multiple function nodes in the project be written as “modules” so that they don't have to be loaded multiple times. This would also make the creation of the function nodes simpler and clearer.

Sure .. it should work.
You may have to use functionGlobalContext though to load your module
instead of the Setup tab functionExternalModules

settings.js section :

/** The following property can be used to set predefined values in Global Context.
     * This allows extra node modules to be made available with in Function node.
     * For example, the following:
     *    functionGlobalContext: { os:require('os') }
     * will allow the `os` module to be accessed in a Function node using:
     *    global.get("os")
     */
    functionGlobalContext: {
        // os:require('os'),
    },

OK!
Do you see special requirements for writing such a module?
And I understood, they have to be loaded in the base directory of .node-red.
Or ... not 'loaded' but installed with node.js, right?

i think the code should be in CommonJS syntax .. but im not sure.
Did a small test and this works

Create a utils.js file in ./node-red folder

const utils = {
  add(a, b) {
    return a + b;
  },
  subtract(a, b) {
    return a - b;
  },
};

module.exports = utils;

In settings.js require it

functionGlobalContext: {
    // os:require('os'),
    utils: require("./utils.js"),
  },

use it in Function node

const utils = global.get("utils")

msg.payload = utils.add(5, 2)

return msg
1 Like

GREAT help! :smiling_face:
Will work with with the next project details. Thanks!

By the way .. i read on the forum that some people store some helpful Functions in Context ..
you could use an Inject node to create those on flow load and call them in a similar fashion (global.get("myFunctions"))