Frontend Tips Episode 19

Let's Checkout Remix ... And Compare It To Next.js

In this video we are going to checkout Remix. I’ve been playing around with Remix for the last couple of days. This video is mostly going to be about that journey and how Remix compares to Next.js.

Remix is a React framework similar to Next.js and I would say that it’s the only real competitor to Next.

It is focused on web standards and modern web app UX. Although Remix is pretty new to Open Source, it has been around for about two years now, but as a payed software that was recently Open Sourced.

The main selling point of Remix is that it embraces web standards and tries to leverage them to provide great user and developer experience.

Remix is trying to bring old school web development practices and patterns to the modern JS world. So if you are and old school developer like me these things are going to be pretty familiar to you.

Philosophy

Remix philosophy consists of few parts:

Embracing Server/Client model - which means that if you are doing things Remix way, most of your data is going to be coming from the server - there is no Static Site Generation or Incremental Static Generation in Remix, only server side rendering, for which Remix provides very nice APIs to make your life as a developer easier.

If you wanna make your site faster this may sound a bit counter intuitive, but since you can transform your data on the server this means that you are sending only the data that the user needs on every request, so your payloads can be pretty small.

If you are using modern web infrastructure combined with native web features like prefetch this can make your site very fast even without serving mostly static content.

Remix is very easy to deploy and plays nicely with Vercel, Cloudflare Pages, Cloudflare workers, Fly.io and many others, so you can easily serve your Remix site from the servers that are closest to your users using CDNs.

Another core philosophy is that it embraces native web standards like HTML, HTTP, Web Fetch API, Request, Response, URLSearchParams and others that already live in your browser.

Progressive Enhancement is another big thing for Remix, and because of it, data layer of Remix can function with or without JS. It uses JS to provide nicer User Experience but you can add or remove data from your data source without using JS at all, because Remix knows how to work with the lowly <form> tag that has been around for 20+ years, and it can send the data to server without JS. Of course as you will see in this video Remix augmented the <Form> tag for 21 century, but it can also function like it’s 1999.

Setup

So now that you have general idea what Remix is, let’s get our feet wet and let me show you how I remade the site from Directus and Next series in Remix.

Installation of Remix was breeze, I managed to get most of the functionality that we have in that app in just four to five hours.

Keep in mind that I already had a lot of code that I could reuse from that app, and I skipped the mini cart and sign in functionality because i didn’t wanna learn another library for authentication. Since we used Next Auth in Directus Next series, and it can only be used with Next.js.

However there is a library called Remix Auth that you can use for that, and it seems pretty similar to Next Auth. So if you need authentication in your app you can check that out.

The only thing I installed when remaking this app was Tailwind, so that I can have the same design that we had in DIrectus Next app.

To install Tailwind you can just follow a quick guide on Tailwinds website, and you’ll be good to go in no time.

When you open the app in your editor you will see a folder structure that is similar to Next.js except all the important stuff is in the app folder. And in app folder you only have routes directory. Which is very similar to the pages directory in Next.js, because just like Next - Remix uses page based routing. So whatever you add in there will automatically get its own route.

This is the folder structure that I ended up with when the app was finished.

Styles directory is generated by Tailwind, and all the other folders are pretty much just copy and paste from the Next.js site, except I needed to save them into app folder as opposed to the root folder of Next.js app.

If you wanna see all the code there will be a link in the description to the GitHub repo that you can browse through.

Products, categories, and Filters.

First thing I wanted to do was setup the homepage. And on the homepage we have few interesting functionalities. One is getting all of our products from Directus, getting all the categories for the Filter and also filtering functionality itself.

Homepage is of course index.jsx file in the routes folder. Now, my Next app uses React Query to get the data and to filter it. However this is not the Remix way, because, remember Remix respects the Server/Client philosophy, so it would be nice to embrace that and get the data from the server instead from the client.

So I removed the React Query part of the code, and leaned in to the server.

And this is not anything new, because Next.js does the similar thing with getServerSideProps just here it works a bit differently.

First you create models directory and in it I created a file called index.server.js here I added all of the getter functions for my data.

And if you have been following my Directus Next series you can see that here I’m pretty much using the same functions for getting the data. And also the same GraphQL queries that I have been using on the Directus Next site.

You can return whatever you need from those functions. I’m exporting functions for getting all of my products, categories, and a function for getting my filtered products that accepts an array of category IDs to filter those products.

Now back in index.jsx you need to export a loader function that will talk to the server and get your actual data.

For categories it’s easy, you can just use useLoderData Remix hook and get it from there. Products are a bit more complicated because we need to filter them.

So for that I’m using the useFetcher Remix hook which will allow me to first of all display all the products. But when user selects a category it will send the category IDs to the loader function which will run a different different getter function to get my filtered data.

Our fetcher is called products in this case, and the fetcher has a submit method on it. So whenever the state of the selected categories change it will submit it to the loader.

And loader will receive a get request which we can parse, and then call the getFilteredProducts function with an array of IDs as a parameter to get the filtered products.

This Workflow is very similar to the Directus Next app, except here all the data fetching is happening on the server and without the need for ReactQuery.

And if we check our front page everything is working as expected.

Meta

There is also a difference how Remix handles meta tags compared to Next.js. In Next you would import Head component, add it to the beginning of the layout on your page and then add the actual tags there, like <title> , <description> and whatever else you need.

In Remix you would export meta function for every page, and that would overwrite all the default tags that you can define in root.jsx. root.jsx is similar to _app.jsx in Next.

Also you can add dynamic data to it, by passing in the data variable which will then have access to all the data that you get from the loader function on that page.

I’m doing that on the single product page to set the title of that page to be the name of the product.

Dynamic routes

Now, to Link the product to the product page you first need to define that page. You can do that almost identically to Next.js, except you would use dollar sign notation for defining dynamic parts of your route instead of square brackets.

In Next you would get the page by slug by writing [slug].jsx but in Remix that page would be called $slug.jsx.

Now, my case is a bit more complicated because I don’t just wanna display the name of product in the URL but I also wanna display a category. So I would have: /products/product-category/product-name .

In Next and in Remix you could create a folder called products, and in it you would create another folder called $category or [catgegory] and in it you would add a file called $slug.jsx or [slug].jsx for Next.js. So this is almost the same in both frameworks.

But, in Remix you could also just create a file with the name: products.$category.$slug.jsx and you would get the same thing, which is cool. So I decided to go with that for my single product page.

Also I suggest to read up about Nested Routing in Remix which is really cool. You can do that on this address. https://remix.run/docs/en/v1/guides/routing

To link my products to the single product page, I used the Link component, which is also similar to the Link component in Next. Except in remix you don’t have href property but instead you use to property. And also you don’t need to wrap Link component around anchor tag like you need to do it Next.js.

You can see the link to my products in the ProductCard.jsx and you can see the difference between Next and Remix. It’s very similar for the most part. The only difference is the href property and the missing anchor tag.

In Next.js I added the Header component which holds the Logo of the shop and navigation in _app.jsx . As mentioned before Remix has a file called root.jsx that serves the same purpose. So we can add Header component that is visible throughout the site there.

Sign up

And there is just one more thing that I wanna show you, and that is the Form component. Which I already talked a bit about at the beginning, and said how it embraces web standards and old school way of dealing with forms.

On Sign up page you can register and create a new user in Directus. To do that in Next we used useMutation hook from React Query, and we would get the data from the form by creating handleSubmit function, for which we would prevent default functionality of the form and then send the data to the server from there.

This is the usual React pattern.

But since Remix embraces the form we can do things a bit differently. So first of all I changed form to be Form with capital F. Fun fact here is that you could leave it as just form with lower case F, and it would also work, it would just reload the page on sending the data, because that is what forms do, and that is the reason we need to use preventDefault in the Next version.

In Remix I just added the method of post to the form, and I want it to do an action that is defined on the page it is on. But you could also add an action that will get instructions from another page.

Then you need to define the action by exporting action function to which you pass a request object. And then you can easily access the data from the form by using formData.get function.

When the data is defined I just send it to the server with createUser function, which I defined in the user.server.js file in models folder. Function for sending the data is the same as in Next.js version of the site.

Now I’m waiting for the response from the server, and if I get create_users_item to be equal to null I can return an error. Since I’m using Directus this means that the user already exists.

If the user does not exist then I can just redirect the user to the thank you page after it’s created on Directus API.

Now if we get an error we can get that information by using useActionData Remix hook. And then we can display an error in our layout like this.

Conclusion

Of course there are a lot more things to cover about Remix but I cant do that in one video. This video is just for you to get a taste of what is possible in Remix and how it works.

My time with the framework was for the most part very enjoyable.

I think it’s an all around great framework that is just going to get better with time, and is a real competitor to Nextjs. And competition is going to be great for us developers.

If you wanna take a look at the code I used in this video you can check it out on Github.

Wanna ask a question about video?

Like This Video?

Support it by sharing it ;)

© Watch And Learn,2024