Today, I found this tutorial made by DHH on how to use React with rails, without webpack by using the new import maps with htm which basically gives the browser the ability to read ES6 and React’s JSX.
If we choose this path, there will no longer be big chunks of JS build, but each file will be served through the assets pipeline.
What I’m not sure about is how would our engine plugins work with that,
and how would our build and packaging process would be affected.
I did indeed link the blog post, but the video does demonstrate that it looks so much easier. Thanks for that!
Perhaps this should be the goal instead of upgrading webpack from version 3 to 5.
Excellent question. I do think foreman-js might become obsolete, in favor of including certain parts in Foreman core. Since there is no transpilation going on, I think everything would live in the global namespace and plugins might be able to “just use” what core provides.
Today we’re on Rails 6.0 (people are working on Rails 6.1/6.2), but it would be very interesting to see how much a very minimal proof of concept using Foreman and Rails 7 without webpack would bring. If we can even just show the login screen (which is React rendered), that could give us some idea.
@ezr-ondrej since you’re working on the Rails migration, do you have any idea how feasible it would be to run on Rails 7 in a development setup?
We will still need to ship the modules somehow because we do support offline setups which can’t access the internet. However, it will be interesting to see how can most efficiently deal with this.
That’s interesting. Would that mean we’d have to ship the whole node_modules directory? Does that mean we could patch JS files on production like setups?
It should take some investigation. What it relies on is having ECMAScript Modules. Webpack has traditionally been used because browsers didn’t implement this, but by now we can rely on browsers to do so.
Looking at importmap-rails it looks like you can ship a node_modules directory and patch the JS files. It all becomes plain file serving again instead of transpilation.
This may have serious consequences for how we ship things though. Needing a complete node_modules directory can be quite large. On the other hand, if we don’t need any development tooling (babel, webpack, etc) it may be much smaller than what we have today.
Another thing that would be interesting to see is wether we can avoid the duplication of node_modules across plugins that makes their 1.5GB * plugins amount which can easily become 10GB… based on what we saw in @Shimon_Shtein container POC, please correct me if I am wrong…
Maybe if it’s part of the assets pipeline it will solve the duplication.
Also we don’t want to load huge bundle files, but if foreman-js vendor will just store all the supported libs versions and on run time it will just add lib per html head script, e.g <script …react.js><script… patternfly.js> then I guess it’d be a good solution.
I think esbuild might be a really cool option to get away from webpack.
But if I understand the two videos above correctly, import maps alone would require us all (foreman, katello, and all other plugins) to restructure almost every component, switch to CSS from scss, and would likely require a ton of other random replace/rewrites of imported component libraries.
Perhaps you could have esbuild only compile the scss to css, and have import-maps handle react, but even then the work involved would largely be a restructure of all react components.
No small amount of work.
I’m also curious to see if the whole thing would explode when you attempt to render a Patternfly component.
I’m definitely on board for faster compilation and the centralization of modules (and deleting foreman-js ).
My only concern is how possible is this really?
If the problem is node modules and not wanting to repeat them in each plugin, have we considered using something like single-spa or other micro-frontend infrastructures with import maps within the parent?
I’ve done that before and although the parent had a bit of a bulky node_modules file, all child apps were fed from there, meaning a single node_modules to rule them all. Micro-frontends also support parent state much in the same way we have our redux stores passed around today.
The benefit of that path would be that the majority of the front-end codebase could be left alone, it would just be creating a new framework to patch things into.
TLDR: If you are planning on a rewrite of all our front-end applications, we should probably also consider some more proven web technologies no?
as for the React render/returned JSX that needs to be wrapped by htm function,
I was thinking that we could add a centralized render wrapper in core that would take care of it,
but then it is still a lot of work to update each and every component we use, and probably means we can’t import directly from Patternfly(?)
but maybe we can use a modified version of React that parse the JSX as a htm string,
not sure if that would work well, but I am sure it’s a very ugly solution.
so, in this case, we could use the other suggestion of esbuild.