Deploying a React/Rails website - why two apps?

Posted by Alex Engelhart on August 3, 2020

When I first gave thought to deploying my final project - making my Rails/React app available for employers and recruiters to look at - I immediately thought of putting it on Heroku. I knew this would involve some refactoring on my backend to make it work with PostgreSQL, but that turned out to be a rather painless process. When it came time to deploy my frontend, though, my mind rebelled. It’s all part of the same app! How do I get it to work when I’m having to create two apps? And why would you set it up that way in the first place? As I thought about it more, I realized that in this case, the “how” explains the “why.”

To answer how to make it work, it turns out that Heroku does in fact support React apps by default. Heroku takes advantage of the defaults provided by the create-react-app package to enable you to run React without any additional configuration. Assuming your React app is working on your local machine, you should be able to simply follow Heroku’s instructions to deploy the app. Once there, you will need to change your API calls to point to the URL of your backend app (you should have coded this so you only have one place to change it), and possibly change your rack-cors settings in the backend to accept calls from the new location.

Still, for someone who may have just gotten done learning about MVC structure in a Rails-only app, this may seem like a lot of work. Why can’t we just fold the whole thing into a single app and be done with it? The answer is that while a single-app setup may work fine for smaller apps, as you start to expand your functionality that one app is going to become very bloated, very fast. As your program expands, you are going to want to start breaking up your app into multiple smaller apps, or microservices, that interact with each other but that otherwise stand on their own. This makes maintenance far easier; your codebase becomes easier to understand when looking at it, and you can expand your service without having to overhaul your entire archictecture. Think of it like the separation of concerns principle in object-oriented programming, but on a project-wide scale.

For example, say I have a dictionary website that allows users to build sentences in Ithkuil. All is well until suddenly the author of the language announces a major revision, and suddenly you realize that you want to include the new language as well. Now if I were making my project into a single app, I would need to include the new functionality for the new language directly into the code of my original project, making sure that I didn’t break anything in the process, in addition to all the work revamping my front end to accomodate the change. By breaking out the new language into its own service, I can treat it as a totally separate venture from the original API without having to worry about the interaction between the two services at all. Importantly, by having already broken out your frontend as its own service that interacts with your backend via API calls, rather than having it be an integrated part of the app, you can set up your new components in basically the same way you did previously - possibly even using the same classes with some additional parameters for the separate API signiature.

Obviously, using a microservice-oriented architecture isn’t going to work for everything - you might not have the means to run a million services concurrently, and writing tests can become more complicated. Still, it’s a pattern that many companies will be expecting candidates to know coming in, and having experience with separating front- and backend into separate apps is a nice introduction to thinking about the concept.