But, I have to say, after spending some time with it…
There’s something special about Remix.
Throughout my time with the framework, I found myself falling more and more in love. It feels like the creators behind React Router have really struck gold with this latest project. As a fullstack developer, I feel like it solves so many of the problems I’ve experienced with modern web development.
I love React, but…
I think the Reactification of the web has caused more problems than the library was originally built to solve. In fact, I don’t know if we can just call it a library anymore. It’s a framework that has never wanted to be. And because of that lack of intentionality, a lot of jank gets polyfilled into the framework of React through its “ecosystem” of third party libraries.
Basic things like routing, app state management, and data fetching – things that are tightly integrated with old-school web frameworks like Rails, Flask, or Laravel – don’t come for free with
create-react-app. And a lot of these tools break fundamental behaviors of the web in favor of “simplicity” which really just means working well with React’s UI rendering patterns – which can sometimes be anything but simple.
I’ll admit though that it took me a while to realize just how backwards “modern” web development is. Building web applications with React causes developers to perform anti-patterns that scaffold their code with ways of working around the web instead of with it. The next time you write
e.preventDefault() in an
onSubmit handler, you’ll see what I mean.
But I overlooked these problems for years because I was blinded by how good of an experience React is when it comes to actually building interactive web pages. So, when Remix’s homepage opened with,
Focused on web fundamentals and modern UX, you’re simply going to build better websites.
I was intrigued.
So, what is Remix?
There’s a moment in a promotional talk where Ryan Florence, one of the Remix co-founders, is asked this exact question. He answers by saying,
It’s a hilarious one-liner, but don’t get the wrong impression – he doesn’t mean that Remix is a framework stuck in the past. What Florence is saying is that Remix is a framework designed as an ode to the web in a way that maybe only more senior developers will understand at first glance.
Remix couples web fundamentals like the client/server model, HTTP caching, and native HTML forms with modern UI tools like dynamic page refreshing, nested routing, and React to create a truly remarkable way for developers to create fast, interactive, and portable user experiences.
You can read all about what makes Remix different on their philosophy page. Right now, I want to take you through some of the features that really stood out to me.
Let’s talk about server-side rendering (SSR).
When I started at Simple Thread, I was shocked at how many of our applications are still built with SSR frameworks like Rails or Django. I seriously thought to myself, “Pshh, these senior developers are so stuck in their ways – they aren’t even embracing modern web tools”.
😮💨 *sigh*. Oh how naive I was.
However, the Remix team, just like our team at ST, knows that SSR isn’t a dinosaur – it’s a shark 🦈 – and Remix brings back the client/server model in a big way. That means no more skeleton UI, loading spinners, code-splitting, static rebuilds, or poor SEO performance. Just blazing fast sites that fetch and send what the user requested when they requested it.
But that doesn’t mean we’re back to dealing with full page reloads or that we have to give up our instantaneous feeling interactions. This is still a React-based framework at the end of the day, and Remix uses the things React is best at to provide a few key progressive enhancements: nested routes, form handling, and error boundaries.
Routing in Remix.
Routes are the standout primitive in Remix – no surprise coming from the team behind React Router. At their core, Routes are modules that handle loading, mutating, and rendering data in your application – all from a single file. You can think of a Route as the view and the controller in an MVC framework. The basic workflow is that Routes export three core functions:
action, and a React functional component.
loader is the
GET endpoint for the route which fetches the data needed for the exported component which can be accessed through the
useLoaderData hook. The
action is the
When it comes to actually routing these routes (oh boy), at a high level the framework borrows a similar file-based routing technique employed by competitors like Nextjs. However, the team behind React Router has brought a fresh take on nested routing to Remix deeply inspired by their previous library.
Remix’s nested routes are more like child routes in React Router. That means that a Route doesn’t have to represent an entire page in your application. Instead, Routes can represent parts of a page layout. The diagram on their homepage explains the concept better than words can.
Essentially, parent Routes can contain an
<Outlet /> component that will trigger the rendering of a Route tree. Child Routes whose location matches the browser’s location will be injected into the page at its parent’s
<Outlet />. Those child Routes can still have their own
action functions which means that the componentization we’ve grown to love in frontend development can now blur into backend development – super cool.
There’s one feature of Routes though that I absolutely love and is often overlooked.
Route based error handling with ErrorBoundary.
Along with exporting a traditional React functional component from a Route, developers can also export two other functional components:
CatchBoundary. These components are incredibly powerful because they automatically get rendered in place of your main component if the
action functions return response statuses with
That’s awesome in itself, but combined with nested routing, that means that if a part of the page layout returns an error, it only effects that part of the page. The rest of your layout is still fully interactive. That’s powerful in terms of UX during failure states.
But that’s not all. Did I also mention Remix allows you to…
Ditch your form library.
Unlike other frameworks like Nextjs that focus solely on helping developers retrieve data, Remix helps developers mutate data in their applications as well. They do this by leveraging good ol’ HTML forms.
Remix comes with a
<Form> component that acts as a wrapper for the traditional HTML
<form> element. When a user submits a form in Remix, the Route
action that form belongs to is called, and all of the data on the page is automatically reloaded. It’s super slick.
The coolest thing though is that
Actually, it’s important to mention that…
I could go on.
There’s so much more to talk about with Remix like performance, portability, and how it compares to fullstack frameworks like Nextjs, Redwood, and even Rails. If you’d like to see articles on those topics or anything else Remix related, please leave us a comment down below.
For now, I’ll conclude with this.
I’ve fallen in love with Remix.
The Routes system, although complicated to understand at first, enables developers to build features cleanly in a single file. It couples the developer experience with the user experience and unites backend and frontend developers. The fact that apps built with Remix can basically run anywhere means that Remix easily integrates with the rest of your stack and makes your code incredibly portable.
But more than that, the team at Remix has said they wanted to build a web framework where developers, “spend more time reading the MDN docs than the Remix docs”. They are so passionate and committed to web fundamentals that the following quote from their website I think is truly the best argument for using Remix on your next project:
“Learn Remix, Accidentally Learn The Web”
Thanks so much for reading. If you like this article, please share it on Twitter and mention us @simple_thread.
Loved the article? Hated it? Didn’t even read it?
We’d love to hear from you.