Our journey from Rails to React, pt 2: migrating views incrementally

Carlos Morales Pereira
Barkibu Development
3 min readSep 16, 2022

--

We like to migrate taking baby steps

As explained in part 1, before we even started migrating from Rails to React, we already had our components organized, thanks to Atomic Design. It was time for the real migration to start!

Swapping the whole project at once could take us several weeks. We like to work in small iterations that continuously add value to our users, so we needed to find a way to switch our views incrementaly.

Hacking the /public folder

Our plan was to switch views to React, one URL at a time, while Rails would keep serving the rest as before.

We installed Gatsby (our React framework of choice) in a /static_generator folder in the root of our project. Then, we configured our npm run build task to move the static files, generated by Gatsby, from /static_generator/public to /public.

Example:
/static_generator/pages/my-url.js
Gets compiled as:
/static_generator/public/my-url/index.html
Moved to
/public/my-url/index.html
Thus, accessible as
mydomain.com/my-url/

One small caveat of this approach was that, to prevent git conflicts, we needed to delete everything inside /public and add that folder to .gitignore. To keep old Rails static files working, we first moved them to /static_generator/static. Gatsby copies everything in that folder to /static_generator/public so, at the end of the build process, those files were moved back to their original /public folder. What a roundtrip!

Hamsters running in a wheel
Our files: moving a lot to end up in the same place.

With this, we got files in the /public folder served by Rails and URLs worked fine. We didn’t even need to care about controllers or routes for that. However, for dynamic URLs (such as mydomain.com/my-resource/(UUID)/) there was not a direct match between Gatsby files and final URLs.

In those cases, we had to create a page with dynamic params in Gatsby, first:
/static_generator/pages/resources/[uuid].js

Strings in brackets [] are available as params in Gatsby.

Then, we had to explicitly tell our Rails controllers to return the static files:

class ResourceController < WebController    
def show
render file: ‘public/resources/[uuid]/index.html’, layout: false
end
end

With this, we were able to render the views, but those still had no access to Rails data. We added a simple API for that, which React consulted with the uuid param.

Automatic deploys (or kind of)

The last step was launching the builds automatically. Those take up some time, so we hoped to be able to run gatsby build just when changes in the /static_generator folder were merged into master. Changes to other parts of the project shouldn’t trigger unnecessary builds. Sadly, we couldn’t.

Heroku reads the root package.jsonof a project automatically on each build, caching node_modules. However, reading package.json inside other folders doesn’t work (or we couldn’t find a way 😅, if you know one please leave a comment).

We had to duplicate the dependencies in both files and call the child from the root file:

“scripts”: {  
“build”: “cd static_generator && ../node_modules/.bin/gatsby clean && ../node_modules/.bin/gatsby build — prefix-paths && cp -R public ../”,
}

Summary

The process has a couple of downsides, but those don’t outweight the most important benefit: we didn’t have to monopolize all of our development resources in the migration for weeks and could, instead, migrate gradually.

--

--