Introducing Remix
It’s intuitive to think of Remix as another React framework. Still, the team behind Remix stresses that Remix is not a React framework but a full stack web framework – an important distinction.
In this first section, we will summarize what it means that Remix is a full stack web framework. First, we will look at the web framework part and explain why Remix is genuinely a framework for the web. After that, we will highlight why Remix is full stack.
Remix is a web framework
The main reason Remix is a web framework is its deep embrace of the web platform. Remix aims to enable a “fast, slick, and resilient user experience” by using web standards. HTML forms and anchor tags, URLs, cookies, meta tags, HTTP headers, and the Web Fetch API are all first-class citizens in Remix. Remix’s conventions, levers, and primitives are thoughtfully designed abstraction layers of existing web APIs and standards. This sets Remix apart from other popular frameworks that feel more decoupled from the web platform.
The Open Web Platform is the collection of standards defined by the World Wide Web Consortium (W3C). This includes JavaScript web APIs, HTML and CSS, accessibility guidelines, and HTTP. The web standard moves at a much slower pace than the industry standard does. New web standards take a long time and go through many iterations before being released, and it’s even longer before all browsers support them.
As a web developer, your resources are limited. To make the most of your time and energy, it’s essential to focus on learning the core principles of the web, which will be applicable regardless of the tools you choose. Learning the foundations of the web is transferable knowledge that benefits you regardless of what frameworks and libraries you use. When using Remix, you will often refer to the MDN Web Docs instead of the Remix documentation. Learning Remix means learning standard web APIs.
React plays a vital role in Remix. Remix leverages the latest features of React where it makes sense. With React 18, React is becoming more sophisticated. React’s latest features are more tailored to framework authors than app developers. Remix provides necessary abstractions to take advantage of these latest advancements.
When paired with React, Remix utilizes client-side routing and data fetching, creating a similar experience to building single-page applications (SPAs) with React. However, Remix has a broader scope than React and addresses additional concerns in web development, such as caching, user sessions, and data mutations. This makes Remix a web framework.
Remix is a full stack framework
Let’s see why Remix is full stack. Remix embraces the client/server model of the web platform. It orchestrates both the frontend and the backend of your web application:
- On the server, Remix acts as an HTTP request handler
- On the client, Remix orchestrates a server-side-rendered React application
Remix acts as a frontend and a backend framework. These two frameworks are independent pieces executed in different environments (the browser and the server environment). During your app’s runtime, the two frameworks communicate over the network.
During development, you create one Remix application where the client and server code is nicely co-located in one /app
directory. We can even write client and server code in the same files.
The following code example showcases what a page/route file looks like in Remix:
// The route's server-side HTTP action handler export async function action({ request }) { // Use the web Fetch API Request object (web standard) const userId = await requireUserSession(request); const form = await request.formData(); const title = form.get("title"); return createExpense({ userId, title }); } // The route's server-side HTTP GET request data loader export async function loader({ request }) { const userId = await requireUserSession(request); return getExpenses(userId); } // The route's React component export default function ExpensesPage() { // Access the loaded data in React const expenses = useLoaderData(); // Simplify state management with Remix's hooks const { state } = useNavigation(); const isSubmitting = state === "submitting"; return ( <> <h1>Expenses</h1> {expenses.map((project) => ( <Link to={expense.id}>{expense.title}</Link> ))} <h2>Add expense</h2> <Form method="post"> <input name="title" /> <button type="submit" disabled={isSubmitting}> {isSubmitting ? "Adding..." : "Add"} </button> </Form> </> ); }
In the code example, we use Remix’s route module API to define a loader
function for server-side data loading, an action
function for mutating data, and the route’s React component for rendering the UI.
Remix co-locates server-side request handlers and the app’s route components. This makes sharing code between the client and server way easier and provides full visibility and control over how our app’s frontend and backend work together.
On the server, we handle incoming HTTP requests and prepare responses using Remix’s action
and loader
functions. In the code example, the server-side request handlers manage user sessions and load and mutate data. We use web standards such as the Fetch API, FormData
, and HTTP cookies.
In the route component, we access the server-side-loaded data and read transition states with Remix’s React hooks. We further use Remix’s Form
component to define a data mutation declaratively. On the client, Remix runs JavaScript to enhance the browser’s default experience. This is where we utilize the power of React to compose dynamic UIs.
Remix is a web framework that lets you take advantage of the full stack. Remix truly allows you to unlock the full potential of the web platform for your React development.
Now that we have introduced Remix, let’s dive into its philosophy.