About making @node-red/editor-client module based (with typings one day)

Hi everyone,

For several months, i am working around a project using Node-Red as a dependency.

In my case, the Node-Red editor is in fact used in a one-paged SvelteJS app (it could have been an Angular or React app, the problem is the same).

To "import" the Node-Red client inside my client-side application, i needed to adapt the file "@node-red/editor-client/public/red/red.js" manually, which is very inconvenient to be able to update Node-Red.

If possible, i would like to code this summer around a future pull request making @node-red/editor-client module based (making it importable with any front-end framework), and a refactoring of these files to use "const" & "let" instead of "var" and implicit variable declarations.

Please be free to give me advices or to tell me if something is wrong here.

Alban Moizan

Is it possible you could share what steps you use to make it "importable" - I assume you make it ESM compatible?

I am not sure of your level of development (so apologies if this is something you already understand) - this is a bigger task that it may first appear due to how the parts are assembled (in grunt) there is possibility that changing everything to const/let could clash and/or introduce (scope) errors - but I agree it is a worthy task (much of the var code has been around a looooong time - for supporting IE - but we have now dropped IE support, the timing might be right for this activity).

I cannot personally give you the go ahead but I am certain other contributors / maintainers will chime in with advice.

Yes I want to make the whole @node-red/editor-client/src/js folder ESM compatible (and it will take a long time), in my opinion it will be very useful.

If I keep your current way to create @node-red/editor-client/public/red/red.js, I will basically need to make vendors dependencies, come with NPM, make RED a constant, and export it at the end (I think).

If everything works, I will probably then add Typescript typings.

For now, I only made a usable red.js file inside another front project, but I won't use it since it isn't compatible with the 3.0.0-beta.x.

Sure, it won't be that easy, but it will be useful to have less sides effects and to have a codebase easier to contribute.

I understand, I will still start coding in this way, and will try to pull request at the end (unless someone tell me that it is not allowed)

Thank you for replying that fast, I will keep this topic in touch if I need to add anything.

(PS: I won't be always replying fast as I am writing from France)

I've also been looking again at ESM, in my case just for parts of uibuilder. I stumbled upon esbuild which has proved a god-send since it let me write a modern (ES2020) front-end library and then output ES2019 ESM and IIFE versions from the single codebase. It appears to be about the only general build tool that genuinely understands current JS.

I have several times started to look at converting some of the back-end code to ESM though and quickly came to the conclusion that it is much harder. It is easy enough to include CommonJS modules into an ESM module in node.js but pretty well impossible to do it the other way around even under node.js v16 - unless you want to rewrite ALL of your code to be promise-based from the top-down. A horrid thought.

I think that since you are only wanting the editor, you should be in a better place though.

In the process of rewriting my front-end library, I had to learn far more than I really wanted to about ESM and the complete cockup that the JS standards body have made of the whole thing. Like the fact that you can't really mix ESM scripts with other scripts very easily since they don't talk to each other. The lack of top-level await also makes dynamic imports very hard to integrate.

The problem with any activity like this is it will quickly get out of sync with the work we're doing in the code and a single PR that modifies everything is not going to be very welcome.

I'm in two minds as to whether this is something we really want to do. The argument that it makes the code base easier to contribute to is entirely subjective and doesn't really feel very compelling to me.

I do acknowledge the code base is in need of a tidy up (const/let etc)... but I would also point out that more bugs have been introduced by changing existing code to use const/let than exist because of the use of var.

We also have to consider the impact this has on other people already embedding the editor in the current form. Moving to ESM modules would be a breaking change for those users - so not something we'd do casually in a minor 3.x release.

I think there may be a half way house.

If the change for ESM can be optional (for example a grunt script builds a red.esm.js out of red.js and whatever else is needed to make ESM compatible) then would that satisfy your requirement?

That's exactly what I did with the new client. esbuild lets you create multiple outputs.

1 Like

This might be too long to fully rewrite these thousands lines of code in modern JS unless there were a team only working in that purpose, but yes, tools as esbuild are the best way give browsers some JS they can understand.

Sure, that's why I don't want to modify everything, it would be too long, and probably not working as well as the current process.
I mean, the idea is to make it exportable, which is not that hard if we keep the grunt current build which basically put every files in one.
The only big issue is that implicit declarations are not allowed in modern JS, and there are implicit declarations (mostly in for loops) in the code base. But it isn't that hard to modify.
Then, for var declarations, I can just let them here and nothing will change in the scope.

Yes, sorry for saying "easier to contribute", what I meant is that the var and implicit declarations, when concatenated in the red.js file, make scope of variables really hard to understand, and adding a feature can then break anything using the same variable name.

I understand that a breaking change can't be pushed in a minor version to not impact other people, so there are 3 choices i guess :
1 - Having a red.esm.js and a red.js
2 - Calling it a 4.x (but that's weird since the 3.x is still in beta)
3 - You are not ok and I will work in a fork without pull requesting

Thank you again for your replies !

The only global var we define is RED. Everything else is scoped within the file its defined due to the way the code is written. The code base is pretty modular already - just not ESM modules.

A pragmatic first step would be to apply some standard linting rules to safely and systematically fix up any common issues. Once we get 3.0 out of the way, that's something I'd been considering doing anyway.

4.x is scheduled for next April which is when we target each major release (this year is overrunning for a number of reasons... but we're almost there).

If there is a way to generate a red.esm.js as a build step with minimal changes to the editor code, then I can see that would be a far less invasive change and something we could look at.

1 Like

Fine, then I will try to generate esm in a non-invasive way ! Maybe I can find a way to script it so it can be auto-generated.

I think it is scriptable (at least in the simplistic way I made the editor loadable in nodejs as an import some months back (as a test / have details somewhere!))

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.