Rails 7 and new frontend approaches POC

continuing from Using React with importmaps on Rails 7

so firstly, If you haven’t watched yet, there are two small tutorials by DHH based on his post in Rails 7 will have three great answers to JavaScript in 2021+

  1. https://www.youtube.com/watch?v=k73LKxim6tw
  2. https://www.youtube.com/watch?v=Chiu-0EVW3g&t=1s

The current main issues with our build is that

  • we still use webpack3 and having issues migrating from it,
    and since webpack3 is deprecated, the day that our app will fail to compile with newer libraries is getting closer…
  • node_modules duplication across plugins and core
  • we don’t use much code splitting and lazy loading
  • npm installs takes too long
    what else do you think is painful today?

In the first example, I didn’t use build tools at all! :open_mouth:
started a POC project in GitHub - Ron-Lavi/react-rails-importmaps-example with the first tutorial example, with React components and importmaps, using the htm hack to avoid compiling the JSX code.

it worked nicely, I could use a <Clock /> React component which loaded to the browser without compilation :tada:
but on the other hand, when trying to use third party component lib, e.g: @patternfly/react-core the browser totally failed to read it :frowning_face: any help on this would be appreciated!
The other con is that we will need to make a lot of refactoring across Foreman and plugins to make it work.

Luckily, the second option using esbuild worked really well :+1:
I created the main app here: GitHub - Ron-Lavi/react-rails-esbuild-example
and an engine plugin in: GitHub - Ron-Lavi/blorgh

I used yarn and esbuild and it built super quick! into the assets pipeline, from there it’s available for the whole app.

here I managed to use also Patternfly and build Empty State pages for the main app (http://localhost:3000/):

and also for the plugin(http://localhost:3000/blogs):

There are still many questions open whether this could replace our frontend build tools in Foreman, plugins, and then also need to be packaged to offline environments.
but I think this is a good start and what I need is more people to play with the code, or raise relevant concerns.

Thank you!

2 Likes

I think this is exciting. Leveraging built in browser support is great and I’d love to see more of it.

I think the dependency (patternfly in this case) needs to be available as ECMAScript Modules (ESM) and if it uses JSX it probably needs to be converted to use htm since browsers don’t understand JSX.

So short term you may still need to use a builder for dependencies. I wonder if it’s possible to still use all code within Foreman as native code while transpiling dependencies. In htm’s README it’s mentioned you can use a babel plugin. Would that be a possible path?

Since Patternfly is a pretty important dependency for us, would it make sense to reach out to them and see if they’ve thought about this?

I think it was also the images and scss that are shipped with PF… maybe also the JSX,
and I guess it will be painful to refactor Foreman and plugins to use htm =/

maybe it could be a solution but then we need a build tool anyway? I wonder if rails has some solution

I also added a few more known issues that we should try to solve:
The current main issues with our build is that

  • we still use webpack3 and having issues migrating from it,
    and since webpack3 is deprecated, the day that our app will fail to compile with newer libraries is getting closer…
  • node_modules duplication across plugins and core
  • we don’t use much code splitting and lazy loading
  • npm installs takes too long

what else do you think is painful today?

I think it is also worth talking about webpack 5,
@sharvit @MariaAga since you investigated the most about the transition to Webpack 5,
what are currently the pain points of migrating to it? can you share more issues with our build stack?

I saw that rails deprecated their webpacker gem in favor of GitHub - rails/jsbundling-rails: Bundle and transpile JavaScript in Rails with esbuild, rollup.js, or Webpack. where you can decide to use one of the bundling engines: “esbuild, rollup.js, or Webpack to bundle your JavaScript, then deliver it via the asset pipeline in Rails”

Thanks for doing all of this research! I still didn’t check the links here, so I have only one question for now :slight_smile:
What are the downsides of using esbuild?

Currently everything works, but I didn’t get to test it with a Foreman-like needs yet…

@Dewar mentioned webpack5 has module federation feature which I am not sure exist on esbuild.

But the question again, I got the impression we failed to migrate to Webpack5 at the moment, that’s why I went to check esbuild (and also the fact webpacker gem got deprecated)

In case we decide to drop browsers support to old browsers and IE, @MariaAga do you / @sharvit think it will solve the issues to migrate to Webpack5?

@Ron_Lavi I don’t want this to stop you from your investigation into esbuild. I think you just need to make sure that all the things we have today are going to work with it.

If it was a choice between module federation and fast compile time, I would take fast compile time 10/10 of those times.

when developing on the frontend it will reduce much waiting time of bundling after each change :+1:

but on the example I created, I still didn’t reuse node_modules from the main app, which is also one of our goals, right? developers struggle with keeping plugins package.json up to date and packaging can become a nightmare :open_mouth: see: What's up with package.json in plugins? for example
although Foreman-js made it much easier in the packaging part, we still have a way to go

An unexpected breakthrough with the importmaps!
using this gist: https://gist.github.com/rubys/82c7477609f561c4c5fdabb462db26d2
I managed to render regular JSX within the importmaps: https://github.com/Ron-Lavi/react-rails-importmaps-example
@ekohl @sharvit @Dewar

Thanks, @Ron_Lavi for doing this research, this looks promising!

Migrating to a new build mechanism is not something trivial, in particular in a pluginable environment like foreman. I would find it highly important to assure that at least these key features exist:

  • Having hot reload dev server
  • loaders (scss / css, jpg, icons, etc)
  • Easy to optimize (i.e removing duplications, monitoring, and reducing js application size)
  • Easy to maintain (update node, 3rd party libraries)
  • Package all together

I have some doubts with importmaps, I think foreman’s frontend is too complex for this at the moment, and using rails solutions like sprockets for loading js 3rd party assets would increase the project’s coupling by much. I still tend to prefer a separation.

The esbuild looks very interesting, it is very lightweight and fast, though we need to verify if it has the features we need. There are some other build tools (some based on esbuild) which also worth some research. This article compares and summarizes some of these new build tools.

in the last comment, I shared how esbuild can be used with importmaps, so no refactoring is needed basically - we were worried about much refactoring though that seem to resolve using esbuild in rails initializers. but there are still issues there that I didn’t try to solve yet like using Patternfly-react. I think that if it will become too hacky then I would also prefer esbuild or one of the other popular build tools.

I would like to avoid the node_modules duplication we have, and I think that using the assets pipeline could solve that, or using something like module-federation which exist in webpack 5,
@sharvit @MariaAga if you can share a bit more of the difficulties in migrating to webpack 5?