React in Ruby on Rails without webpacker

Image for post
Image for post
Photo by Aleksandr Saenko on Unsplash

There’s plenty of options when it comes to integrating React into a Rails app. All of the gems use webpacker. I have a deep distrust of having node & npm installed on the server and offer a webpacker-free alternative. Not forcing webpacker, backend devs don’t need to hassle with setting and running anything from the node.js world.

We’ll create a sample Rails project which will have a standalone React application in a subfolder. Rails will contain a built version of the React app, meaning that React and everything-node is only needed when changing the React code. To switch between the dist version and live react server when developing locally, we’ll use an ENV variable.

Rails & React setup

Start by creating a sample rails project.

Image for post
Image for post
On http://localhost:3000/ you’ll be greeted by the default Rails homepage.

Next, let’s use Facebook’s create-react-app to initialize a frontend subfolder, which will contain everything-reacty. Note that you can create the React app any way you prefer, create-react-app is used for the sake of simplicity.

If using create-react-app, we may want to change the default port of the server from 3000 to something else, so that Rails can run on 3000. Add an .env file setting the port

Fire up the React dev server:

Image for post
Image for post
It will pop up at http://localhost:3001/. Now let’s connect it to Rails!

Connecting Rails & React

First, we generate a Home controller and delete the default index.html from public.

Set up the routes:

Create the template, containing the element, that create-react-app is looking for:

Upon visiting http://localhost:3000/ you’ll get a blank white page, which is perfectly correct, as the React assets are not included yet. Let’s add the React bundle to the bottom of the application layout (under the yield):

Refresh http://localhost:3000/ to see React connected.

Image for post
Image for post
Well, it’s something.

We can see that application boots, but cannot find the assets. That’s not a problem as you shouldn’t use static images from React. Server them from Rails instead.

Passing data from Rails to React

Let’s edit the React app to display some data passed from Rails. Set the data in the controller:

Add it as a data attribute in the view:

Pass it to the App component in the React setup script:

Print the fruits in the App component:

On http://localhost:3000/, we get the result.

Image for post
Image for post

While the example is trivial, we might pass any sort of information that way — be it API urls, serialized models, constants, translations, etc. — using multiple attributes if needed.

In case we wanted to have multiple React instances on the same page, we’d change the root selector from id to class and tweak the initialize script:

We might even use different components for different root elements, passing different data.

Inside of the initializer, you can set up your Redux store, sagas etc. For a rather complex example, see the setup file of the React portion of sinfin/folio CMS, which enhances the administration console UX.

Building React

We can build the React app with npm run build inside of the frontend folder. That will create some files in frontend/build/static. We want to copy these files to the Rails assets folder. To do that, we can create a simple script in the frontend folder.

Don’t forget to add +x permissions.

Modify the build command in the package.json:

Building with npm run build now creates frontend.js and frontend.css in the corresponding assets subfolders.

Serving the dist version

We’ll instruct sprockets to compile the assets,

and include them in the application layout:

We look at ENV to determine whether we’re willing to edit the React code. When a server is run, the built version is used by default. To develop the live version, one has to start the server with a REACT_DEV environment variable, which is as simple as:

I’ve created an example github repository containing the code mentioned throughout the article.

Written by

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store