Uibuilder + React (socket.io module not found)

Wondering if anyone can assist with the following error (after running npm run start):
/home/pi/.node-red/node_modules/node-red-contrib-uibuilder/front-end/src/uibuilderfe.js Module not found: Can't resolve 'socket.io-client' in '/home/pi/.node-red/node_modules/node-red-contrib-uibuilder/front-end/src'

This is running Node-RED version: v2.0.4
Node.js version: v14.17.4
uibuilder v4.1.0 initialised
Installed packages: socket.io, reactjs

The React server starts fine and I can create React apps as long as no call is made to uibulder, else the above error results. There are no other startup errors.

Any help appreciated.

Thanks
Bob

Can you please provide the actual node-red startup log at least as far as the uibuilder and the error parts?

Can you also confirm whether you are using Docker?

Startup log -

2 Aug 08:46:33 - [info] Context store : 'default' [module=memory]
2 Aug 08:46:33 - [info] User directory : /home/pi/.node-red
2 Aug 08:46:33 - [warn] Projects disabled : editorTheme.projects.enabled=false
2 Aug 08:46:33 - [info] Flows file : /home/pi/.node-red/flows.json
2 Aug 08:46:33 - [info] Server now running at http://127.0.0.1:1880/
2 Aug 08:46:33 - [warn]

Your flow credentials file is encrypted using a system-generated key.
If the system-generated key is lost for any reason, your credentials
file will not be recoverable, you will have to delete it and re-enter
your credentials.
You should set your own key using the 'credentialSecret' option in
your settings file. Node-RED will then re-encrypt your credentials
file using your chosen key the next time you deploy a change.

2 Aug 08:46:33 - [info] +-----------------------------------------------------
2 Aug 08:46:33 - [info] | uibuilder v4.1.0 initialised
2 Aug 08:46:33 - [info] | root folder: /home/pi/.node-red/uibuilder
2 Aug 08:46:33 - [info] | Using Node-RED's webserver at:
2 Aug 08:46:33 - [info] | http://127.0.1.1:1880/ or http://localhost:1880/
2 Aug 08:46:33 - [info] | Installed packages:
2 Aug 08:46:33 - [info] | socket.io, reactjs
2 Aug 08:46:33 - [info] +-----------------------------------------------------
2 Aug 08:46:33 - [info] Starting flows
2 Aug 08:46:33 - [info] Started flows


Docker not used. There are no errors when NR starts. The error occurs starting the dev server.

@TotallyInformation maybe this problem is related to what i noticed also when i used version 4 and we briefly discussed in this thread

uibuilderfe.js Module not found: Can't resolve 'socket.io-client'
could this be solved if uibuilder included socket.io-client in its dependencies ?

in my case I had to run npm install socket.io-client in node-red-contrib-uibuilder folder.

That is not the full log, it is missing the startup information for Node-RED itself.

What dev server?


No, I don't believe so. Your problem was because of the way you packaged your front-end code. There is no indication here that @Bobo is packaging his front-end code in this case.

I hadn't realised that you had done that. Please don't, this will lead to hard-to-spot errors in the future. That is because the version of the Socket.IO client and server typically HAVE to be the SAME.

You need to sort out your packaging instead. As previously mentioned, I strongly advise you to remove socket.io client at least from your package. It really will not be giving you any real-world advantages and will be likely to cause further issues in the future. Otherwise adjust your build configuration to get the client from the version of Socket.IO that is installed in the usual place under the userDir folder.

I understood that the versions of socket had to be the same.
I confirmed that by looking at package.json after running the npm install.
v.4.1.3 for both server and client.

What i didnt understand is the alternatives . Excuse my lack of knowledge on the subject.
you mean instead of using
import uibuilder from './../../../node_modules/node-red-contrib-uibuilder/front-end/src/uibuilderfe.js'

that makes uibuilderfe behave as a module ? i saw some code in the source to handle that for bundlers.
I should have simply used the script tags in my html file instead ?

<script src="../uibuilder/vendor/socket.io/socket.io.js"></script>
<script src="./uibuilderfe.js"></script>

i dont know how to do that :sweat_smile:
thats why i chose Parcel.js which is almost zero configuration bundler hehe

is that even possible since its uibuilderfe.js that is requiring socket.io-client

// @since 2017-10-17 CL: tell webpack that we need socket.io client if running from webpack build
if (typeof require !== 'undefined'  &&  typeof io === 'undefined') {
    // @ts-expect-error ts(2307)
    var io = require('socket.io-client')
}

im confused .. just when i thought learning a bit of javascript was enough :wink:

ps. sorry @Bobo for hijacking your thread.

Yes. Except use the .min. version for the uibuilderfe library, it is already compressed.

uibuilderfe isn't really an issue as it is already wrapped in a way that makes it behave nicely no matter how it is called. You can include that in your build if you like but if you do, you have to remember to rebuild your front-end code every time you update the uibuilder package. For what you get in return, the gain is so small, it isn't worth the possible annoyance of forgetting to rebuild and ending up with a flow that doesn't work because the node-red end is expecting a newer version of the front-end.

Similarly with the socket.io client. It is already packaged nicely for you and you really gain next to nothing by including it in your build. and the same problem applies. If the server gets updated and you forget to update your front-end code, you will be back to that same error again.

Both libraries work just fine as script links and being towards the end of your code, are already loaded efficiently. Both are already packed if you use the .min version (socket.io doesn't use a separate .min version, it is already optimised) so you don't gain much there.

In addition, browser caching will negate much of the remaining benefits including them in build would give you.

Go for simplicity and stability over too much optimisation.

The error occurs when starting the React app as per the example in your wiki.

Full trace log below ...

pi@raspberrypi:~/.node-red $ node-red-start

Start Node-RED

Once Node-RED has started, point a browser at http://10.1.1.200:1880
On Pi Node-RED works better with the Firefox or Chrome browser

Use node-red-stop to stop Node-RED
Use node-red-start to start Node-RED again
Use node-red-log to view the recent log output
Use sudo systemctl enable nodered.service to autostart Node-RED at every boot
Use sudo systemctl disable nodered.service to disable autostart on boot

To find more nodes and example flows - go to http://flows.nodered.org

Starting as a systemd service.
4 Aug 10:48:15 - [info]
Welcome to Node-RED

4 Aug 10:48:15 - [info] Node-RED version: v2.0.5
4 Aug 10:48:15 - [info] Node.js version: v14.17.4
4 Aug 10:48:15 - [info] Linux 5.10.52-v7+ arm LE
4 Aug 10:48:16 - [info] Loading palette nodes
4 Aug 10:48:17 - [debug] Module: node-red-contrib-moment 4.0.0 /home/pi/.node-red/node_modules/node-red-contrib-momen t
4 Aug 10:48:17 - [debug] Module: node-red-contrib-uibuilder 4.1.0 /home/pi/.node-red/node_modules/node-red-contrib-ui builder
4 Aug 10:48:21 - [trace] [uibuilder:Module] ----------------- uibuilder - module started -----------------
4 Aug 10:48:21 - [trace] [uibuilder] uibRoot folder exists. /home/pi/.node-red/uibuilder
4 Aug 10:48:21 - [trace] [uibuilder] uibRoot folder is read/write accessible. /home/pi/.node-red/uibuilder
4 Aug 10:48:21 - [trace] [uibuilder] Copied template .config folder to local .config folder /home/pi/.node-red/uibuil der/.config (not overwriting)
4 Aug 10:48:21 - [trace] [uibuilder:web:setMasterStaticFolder] Using master folder: src
4 Aug 10:48:21 - [trace] Reason for not using master dist folder: ENOENT: no such file or directory, access '/hom e/pi/.node-red/node_modules/node-red-contrib-uibuilder/front-end/dist/index.html'
4 Aug 10:48:21 - [trace] [uibuilder:socket:socketIoSetup] Socket.IO initialisation - Socket Path=/uibuilder/vendor/so cket.io
4 Aug 10:48:21 - [trace] [uibuilder:web:servePackage] Adding user vendor path: {
url: '/uibuilder/vendor/socket.io',
path: '/home/pi/.node-red/node_modules/socket.io'
}
4 Aug 10:48:21 - [trace] [uibuilder:web:servePackage] Adding user vendor path: {
url: '/uibuilder/vendor/reactjs',
path: '/home/pi/.node-red/node_modules/reactjs'
}
4 Aug 10:48:21 - [info] Settings file : /home/pi/.node-red/settings.js
4 Aug 10:48:21 - [info] Context store : 'default' [module=memory]
4 Aug 10:48:21 - [info] User directory : /home/pi/.node-red
4 Aug 10:48:21 - [warn] Projects disabled : editorTheme.projects.enabled=false
4 Aug 10:48:21 - [info] Flows file : /home/pi/.node-red/flows.json
4 Aug 10:48:21 - [trace] [uibuilder:web:webSetup] Using Node-RED ExpressJS server at http://127.0.1.1:1880
4 Aug 10:48:21 - [info] Server now running at http://127.0.0.1:1880/
4 Aug 10:48:21 - [debug] loaded flow revision: 5666ba0aac441d17c1c7fdf66e3631ba
4 Aug 10:48:21 - [debug] red/runtime/nodes/credentials.load : no user key present
4 Aug 10:48:21 - [debug] red/runtime/nodes/credentials.load : using default key
4 Aug 10:48:21 - [debug] red/runtime/nodes/credentials.load : keyType=system
4 Aug 10:48:21 - [warn]

Your flow credentials file is encrypted using a system-generated key.
If the system-generated key is lost for any reason, your credentials
file will not be recoverable, you will have to delete it and re-enter
your credentials.
You should set your own key using the 'credentialSecret' option in
your settings file. Node-RED will then re-encrypt your credentials
file using your chosen key the next time you deploy a change.

4 Aug 10:48:21 - [trace] runtime event: {"id":"runtime-state","retain":true}
4 Aug 10:48:21 - [info] +-----------------------------------------------------
4 Aug 10:48:21 - [info] | uibuilder v4.1.0 initialised
4 Aug 10:48:21 - [info] | root folder: /home/pi/.node-red/uibuilder
4 Aug 10:48:21 - [info] | Using Node-RED's webserver at:
4 Aug 10:48:21 - [info] | http://127.0.1.1:1880/ or http://localhost:1880/
4 Aug 10:48:21 - [info] | Installed packages:
4 Aug 10:48:21 - [info] | socket.io, reactjs
4 Aug 10:48:21 - [info] +-----------------------------------------------------
4 Aug 10:48:21 - [trace] runtime event: {"id":"runtime-deploy","payload":{"revision":"5666ba0aac441d17c1c7fdf66e3631b a"},"retain":true}
4 Aug 10:48:21 - [trace] [uibuilder] Copied common template folder to local common folder /home/pi/.node-red/uibuilde r/common (not overwriting)
4 Aug 10:48:21 - [info] Starting flows
4 Aug 10:48:21 - [debug] red/nodes/flows.start : starting flow : global
4 Aug 10:48:21 - [debug] red/nodes/flows.start : starting flow : fae34a19d6c57224
4 Aug 10:48:21 - [trace] [flow:global] start flow [global]
4 Aug 10:48:21 - [trace] [flow:fae34a19d6c57224] start flow [fae34a19d6c57224]
4 Aug 10:48:21 - [trace] [uibuilder:nodeInstance:test] ================ instance registered ================
4 Aug 10:48:21 - [trace] [uibuilder:nodeInstance:test] node keys: ["id","type","z","_closeCallbacks","_inputCallback" ,"_inputCallbacks","name","wires","_wireCount","send","credentials"]
4 Aug 10:48:21 - [trace] [uibuilder:nodeInstance:test] config keys: ["id","type","z","name","topic","url","fwdInMessa ges","allowScripts","allowStyles","copyIndex","templateFolder","extTemplate","showfolder","useSecurity","sessionLengt h","tokenAutoExtend","oldUrl","reload","sourceFolder","x","y","wires"]
4 Aug 10:48:21 - [trace] [uibuilder:nodeInstance:test] Node instance settings: {"name":"test","topic":"","url":"test" ,"copyIndex":true,"fwdIn":false,"allowScripts":false,"allowStyles":false,"showfolder":false}
4 Aug 10:48:21 - [trace] [uibuilder:nodeInstance:test] Node uib.Instances Registered: {"e7136ec73b6bb59f":"test"}
4 Aug 10:48:21 - [trace] [uibuilder:nodeInstance:test] Number of uib.Deployments: 1
4 Aug 10:48:21 - [trace] [uibuilder:nodeInstance:test] Using local front-end folders in: /home/pi/.node-red/uibuilder /test
4 Aug 10:48:21 - [trace] [uibuilder:web:addInstanceStaticRoute:test] Using local src folder
4 Aug 10:48:21 - [warn] [uibuilder:test] [uibuilder:web:addInstanceStaticRoute:test] Cannot show default page, index. html does not exist in /home/pi/.node-red/uibuilder/test/src.
4 Aug 10:48:21 - [debug] uibuilder : test : URL . . . . . : /test
4 Aug 10:48:21 - [debug] uibuilder : test : Source files . : /home/pi/.node-red/uibuilder/test
4 Aug 10:48:21 - [trace] [flow:fae34a19d6c57224] ------------------|--------------|-----------------
4 Aug 10:48:21 - [trace] [flow:fae34a19d6c57224] id | type | alias
4 Aug 10:48:21 - [trace] [flow:fae34a19d6c57224] ------------------|--------------|-----------------
4 Aug 10:48:21 - [trace] [flow:fae34a19d6c57224] e7136ec73b6bb59f | uibuilder |
4 Aug 10:48:21 - [trace] [flow:fae34a19d6c57224] 1d84c00c0e0f52af | inject |
4 Aug 10:48:21 - [trace] [flow:fae34a19d6c57224] 3ecbdee0aa8a7544 | debug |
4 Aug 10:48:21 - [trace] [flow:fae34a19d6c57224] ------------------|--------------|-----------------
4 Aug 10:48:21 - [trace] runtime event: {"id":"runtime-state","retain":true}
4 Aug 10:48:21 - [info] Started flows
4 Aug 10:48:22 - [trace] comms.open 6I7tepLmTyzixf8qmr/sMDXj1kcNmh9Zv5q/kEfCbHA=

Ah, 10/10 for showing a trace log. However, I'm afraid that you've misinterpreted it. I assume you are thinking this is the error?

4 Aug 10:48:21 - [trace] Reason for not using master dist folder: ENOENT: no such file or directory, access '/hom e/pi/.node-red/node_modules/node-red-contrib-uibuilder/front-end/dist/index.html'

But that is actually just the trace telling you that there is no index.html file in the dist folder for that uibuilder instance. This is perfectly normal.

uibuilder serves up EITHER the contents of the src OR the dist folder. Lacking other information, it makes that decision based on whether there is an index.html file in the dist folder.

Because you are using the latest v4.1.0, you actually have the ability to manually change that delivery.

image

But if you haven't changed it manually, uibuilder continues to do the same check.


So, with that out of the way. Do you still have an issue?

Yes, the original error remains re socket.io. I built a new install on a new sd card (just in case) but same error remains when I go to start the React app.

OK, next step is for you to share your index.html and index.js files.

Also, as with the side-chat with UnborN, can you confirm whether you have a build step for your front-end js? If so, what configuration are you using?

No build step. Index files follow ...

<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport"
    content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="theme-color"
    content="#000000"> <link rel="manifest" href="%PUBLIC_URL%/manifest.json"> <link
    rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico"> <title>React UI - uibuilder and
    Node-RED</title>
</head> <body> <div> <h1> Welcome to REACT-UIbuilder for Node-RED! </h1> </div> <div id="root">
    <div id="app"> </div>
</div> </body> </html>

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

OK, so how is that meant to work?

You have not included in either of those files any method of loading uibuilderfe, socket.io client, react itself.

So clearly something is missing from this picture.

In addition, using import statements in client-side javascript does not work unless you are trying to rely on html components but because you have nothing at all in your html file, there is no indication of that either. The only other alternative is that you do, in fact, have a build step that translates the import statements to a consolidated .js file - but even that should appear in your html.