Earlier today I saw this tweet:
And although I have a lot of respect for the tweet author and for RoR itself I felt like expressing my opinion about why I hope Shopify won't walk that path.
TLDR
In this post I write about our experiences with using a Rails API and separate front-end app:
- Complex hiring process due to the need for specialized front and back end developers
- Communication issues between the front and back end
- Duplication of code for tasks such as validation, authorization, and type definitions
- Maintaining two separate deployment processes and hosting solutions
I also highlight some benefits of adopting Remix as a full stack framework:
- Improved developer experience and greater type-safety
- Simplified hiring process with the ability for any developer to contribute to the full stack
- Elimination of the need for two separate deployment processes and hosting solutions
And explain the opportunities and challenges of filling in the gaps left by the absence of Rails.
Rails: The Good Ol' Days
We've all been there.
Fifteen(ish) years ago, we would develop any web app in a monolithic codebase. Every new web developer would be able to contribute to both the back-end and front-end on their first day because they would know the architecture, where every bit of code belonged, and the responsibilities of models, views, controllers, and services, etc.
If we wanted a production-ready app, we would extend Rails' built-in features with our favorite gems.
The front end was not that complex. We would just sprinkle in a bit of JS and use some libraries like jQuery, BackboneJS, or compilers like CoffeeScript. Progressive enhancement was almost a side effect of the development process.
However, this didn't last long because we wanted a richer UX, and so we entered the SPA era. I'm not going to go into the pros and cons of SPAs, as many people have already done so, but I want to explain why it was a problem for us.
Our Business Problem with SPAs
While we were solving all of our back-end needs with Rails APIs, we were also surfing the React wave, using Flux, Redux, Webpack, CRA, SSR solutions, Flow, TS, and a plethora of packages and tools to stay on the cutting edge of technology.
Our hiring process became a lot more complex because we needed to hire for both the front and back end. It was almost impossible for a developer to be as productive in both stacks, which created little developer silos and made the change of context to deliver any full-stack feature enormous.
We also realized that about 90% of the calls for help in our #devhelp Slack channel had to do with the communication between the apps. Managing the state in the front end and keeping it in sync with the database was the real bottleneck of web development.
There was also a lot of duplication, as things like validations, authorization, and type definitions would have to be done on both apps.
Having two teams, two deployment processes, and two hosting solutions was a hassle, and even using BFF (backend-for-frontend) didn't help much.
We also tried out Hotwire, but it didn't come close to the DX/UX we're used to with React.
Our Urge for a New Stack
As TypeScript evolved and we became proficient with it, we realized the huge benefits we would get if we had our whole stack using it.
So, when Remix came to our attention, we decided to allocate two of our most seasoned developers to do daily R&D to see if Remix would fall short. This process lasted for a year!
During that time, we threw the most complex business problems at ourselves and created some public libraries as well as an internal framework. We figured out ways to migrate CRA + Rails apps to Remix.
After all that time and investment, we feel more confident about our stack than ever!
You Might Not Get the Full Potential of Remix
The DX (developer experience) we achieved is unmatched. We have type-safety from end to end and no code duplication. These two things alone would not be possible with a BFF approach.
Our hiring process is shaping up a lot simpler, and all the developers will be speaking the same language now. Like in the Rails era, any developer will be able to contribute full stack.
We also ditched the cost of maintaining two deployments and hosts per app.
Remix Opened the Door to the Back-end World
To achieve this, we had to find solutions to fill in the gaps left by the absence of Rails. We had to use tools like Prisma, Node mailer, MJML, Bull, etc., because Remix is not a (complete) backend framework.
We had to figure out our architecture, file organization, and recreate some things that Rails had mastered over the years.
We still miss the power of ActiveRecord, but we know that our inferred type safety has been preventing a lot more bugs. We are also aware that we now spend most of our time developing business logic instead of the accidental complexity inherent in SPAs.
As a bonus benefit, we not only re-added progressive enhancement to our vocabulary, but we also have been able to use techniques that we developed in the Rails era - AKA: web standards.
Conclusion
The reason why I hope Shopify will use Remix as a full-stack framework is that not every small company can afford to invest as much as we did at Seasoned in order to achieve the dream stack. If Shopify does it, it will be a huge win for the community, and it will also lower the barrier to entry for small companies to achieve the same DX.
We need a framework on top of Remix! It will happen eventually, whether it's Shopify or companies like Seasoned that do it.
If you see the value in a Remix (or React Router 6.4+) and TypeScript stack, but you are still figuring out how to get there or can't afford to do this research, talk to us in our discord community.