Full Stack Components

Remix is a web framework that gives you the simple mental model of a Multi-Page App (MPA) but the power and capabilities of a Single-Page App (SPA). One of the big challenges of SPAs is network management resulting in a great deal of indirection and buggy code. This is especially noticeable in application state which Remix completely eliminates, but it's also an issue in individual components that communicate with a single-purpose backend endpoint (like a combobox search for example).


In this talk, Kent will demonstrate how Remix enables you to build complex UI components that are connected to a backend in the simplest and most powerful way you've ever seen. Leaving you time to chill with your family or whatever else you do for fun.

Rate this content
Bookmark
Video Summary and Transcription
Remix is a powerful full stack framework that simplifies the integration of backend and frontend code. During the talk, the speaker highlights how Remix allows developers to create full stack components by merging UI and server-side logic within a single file. This approach is exemplified through a demo featuring a combo box that performs a search using the Downshift library. Developers can benefit from Remix's ability to handle authentication in loaders, ensuring secure access to data by checking user authentication before processing requests. The useFetcher hook in Remix is emphasized as a tool for asynchronous data fetching, allowing components to update based on user interactions without causing additional renders. Additionally, Remix enhances SEO through server-side rendering, ensuring content is fully rendered for web crawlers. The speaker expresses excitement about Remix's partnership with Shopify, which brings stability and funding to the framework, promising a positive future for its development. The talk also touches on the potential for publishing Remix components to NPM, allowing developers to package and distribute components with both frontend and backend logic, facilitating easier integration into various projects. Overall, Remix is portrayed as a versatile and efficient solution for modern web development.

This talk has been presented at Remix Conf Europe 2022, check out the latest edition of this React Conference.

Available in Español: Componentes de Full Stack

FAQ

RemixConf EU is a conference where enthusiasts and professionals gather to discuss and share knowledge about the Remix framework, focusing on full stack development.

Epicweb.dev is a project mentioned by the speaker as their full-time endeavor. It is likely a platform or service related to web development, although specific details were not provided in the text.

Remix uses loaders to handle authentication by checking if a user is authenticated before processing a request. If a user is not authenticated, the loader can redirect the user to a login page, ensuring that only authenticated users can access certain data.

Remix enhances SEO by allowing server-side rendering of components, which ensures that content is fully rendered when web crawlers scan the page. This improves the likelihood of the content being indexed and ranked higher in search results.

The useFetcher hook in Remix is used to interact with loaders for data fetching. It allows components to fetch data asynchronously without causing additional renders, making it suitable for updating parts of an application based on user interactions.

Yes, full stack components in Remix can be published to NPM. This allows developers to package and distribute components that include both frontend and backend logic, potentially simplifying the integration of complex functionalities into different projects.

In Remix, a 'loader' is a function that loads data for a specific route. It plays a crucial role in handling server-side operations, such as fetching data, which can then be rendered directly in the UI.

Full stack components in Remix are components that include both the UI code and server-side code, allowing backend and UI integration directly within the same file, enhancing the efficiency of route-based operations and UI interactions.

1. Introduction to Full Stack Components#

Short description:

I'm excited about RemixConf EU and speaking about full stack components. I'm working on Epicweb.dev, my full-time thing now. This talk is a demo of components that include UI and server-side code. We'll be talking about Remix, our favorite full stack framework.

What is up Remix Friends? I'm so excited about RemixConf EU and I'm really excited to be speaking with you all about full stack components, so let's go talk about taking colocation to the next level.

So one thing that I wanted to talk about really quickly is I'm working on Epicweb.dev, if you haven't seen that yet definitely give it a look. It's my full-time thing now, it's awesome. And all my slides and everything for this talk are on my GitHub so you can take a look at that there.

So this talk is going to be a demo of components that include both the UI code as well as a server side code and we're going to be doing a lot of coding and so yeah, buckle up. We're going to be talking about Remix, of course our favorite UI framework. Well full stack framework, not just UI and that's part of what this talk is all about.

2. Exploring Remix Features#

Short description:

Remix allows us to marry the backend and the UI in the same file. We can build UIs that aren't URL-centric, like the Twitter like button. We're going to demonstrate a combo box that does a search. We have an app running with a route for fetching customers. We can export a component that consumes the loader. We're using the Downshift library for the combo box experience.

So Remix allowed us to marry the backend and the UI in a way that has never been done before with the loader and action and our UI all in the same file. And this is a pretty simple demonstration of how that works from a route perspective. So we have our projects route and here we have our loader to load those projects and we've got our form to add new projects and the backend piece for that mutation.

But sometimes we have UIs that aren't like so URL centric, for example the Twitter like button, whenever I click on that like button that's not going to take me somewhere else, I don't only render that on a special page that has a specific route, I render the like button for every single one of the tweets that are on the page and so that doesn't really work very well as something that you'd like stick in a loader or an action for a particular route necessarily and here's another example of a combo box that's doing a search and this is the thing we're actually going to be demonstrating today.

So, I've got an implementation of this app right here, we're not rendering the combo box yet because we are going to build it together and connect it to the backend and it's going to be sweet. So, that's it. It's demo time. So, the first thing is we've got this app up and running right here, we're in the 01.b4 version of the app and we're in the app directory under routes and under this resources directory is where we'll find the customers. So, we're going to have this route for slash resources slash customers and that's going to be the API route that we're going to be using to go get a bunch of customers.

Now, one really cool thing about Remix is that if you don't have a default export of your module, the Remix will treat your module like a resource. And so, what we mean by that specifically is I can say export an async function, whoops, a function, come on, there, called loader and here I'm going to return JSON and that JSON actually is going to come from Remix run node and we'll say hello world. And if I save that and come over here, I can go to resources, customers and I'm going to get hello world. Now, there's nothing special about the resources directory other than the fact that my editor seems to like giving that a special icon, but there's nothing special about this. We can call this whatever we want and it just so happens that the way I like my URL for this to work is to have a slash resources and that's it. So wherever we want that URL to be, that's where the file is going to be. So by having a loader export but no default export, this is just a regular request for like an API request. So with that in place, now we can build some UI that interacts directly with this loader that makes fetch requests. But what's really cool about Remix is that we can actually add a bunch of other exports to this as well. We can export const koala equals Kodi, like it doesn't matter. We can do anything we want to in here and Remix will just ignore it in its builds. So what that means is we can actually export a component in here that consumes this loader and that's exactly what we're going to do. And because I know you probably don't care to watch me write a bunch of JSX, I've actually written all the JSX stuff there. So here's our loader, it's just what we had before, but then we got a bunch of other JSX stuff in here that you, like I said, you probably don't care to watch me do all of that. So skipping over the JSX bit, the most important and interesting bit here is we're using this use combo box, which is a Downshift hook. Downshift is a library I built years ago when I was at PayPal, and it's for making this combo box experience for us. And all we need to do is provide it with the items and we can respond to input value changes as the user is typing. So that's perfect. That's exactly the two things that we need. And with that we're exporting this combo box, but we're still just a resource route. There's nothing special going on here.

3. Implementing Endpoint and Querying Customers#

Short description:

This is just hitting an endpoint and getting the response. We'll flesh out the loader and require authentication. We'll get the URL and query from the request. Search for customers using Prisma and SQLite. Send the matching customers in the response.

This is literally just hitting an endpoint and getting whatever the response that we sent back was. So let's do a couple of things with this endpoint, though. So we'll flesh out this loader.

So for one, I personally don't really want people to be able to hit this endpoint who are not authenticated. So we're going to say, Require User. And we'll pass the request. Now we get that request in our loader, of course, so we'll pass that request. We'll use LoaderArgs. There we go.

And with that, now, I can still make a request to this, but if I go incognito, I'm going to get redirected to the login. So that's nice. Remember, all of your loaders are basically API endpoints anyway. Anybody could curl that URL and get access to everything that you have at that URL. So you do need to protect your loader data, and this is how we're going to do this here.

So, the next thing is, I'm going to get the URL from the request.URL. Turn this into a URL object so I can get the query from URL search-params.get. And we'll just do full word query here. And we want the query to be either, in this case it's either a string or null. We'll go ahead and default that to a string. So it's always going to be a string. So now I can do search customers.

And this is implemented using Prisma and SQLite is how this is set up. But this search customers could be an implementation that makes a fetch request to another downstream service or like a Rails or PHP backend, or whatever. That part is not important. Just the fact that we have some mechanism for sending this query along to where we're going to actually query for the customers. So we'll pass this query along and we'll get our customers. These are the matching customers back. And then with that, we'll send that in our response. So now if I hit that, I'm not going to get anything. If I say, query S, then I'm still not going to get anything because I messed something up.

4. Implementing Search Customer Fetcher#

Short description:

This is the correct query. We're going to use URL search params. We forgot to await, but now we can get the customers and query for specific ones. The special sauce is our useFetcher, which connects us to the UI. We implement the Search Customer Fetcher with type safety.

So no, that is the correct query and query right here and query right there. Oh, this is not good. So we're going to URL search params. Oh, shoot. I'm going to have to start over. Oh, I know what it is. I'm not going to start over. I forgot to await. Silly me.

So now we're going to get the customers. There we go. Okay. So we've got all of our customers there, then we can query for specific ones. And we can just get an array of all the customers that match. So that's exactly what we're looking for for the API route.

Now here's the special sauce. This is what's going to actually connect us to the UI piece of this, is our useFetcher. So Cody the Koala, hello. Here's Cody. Cody is going to tell us we need to implement Fetcher here. So we're going to say Fetcher, or we'll call this Search Customer Fetcher. You can call it whatever you like. It really doesn't matter. And we'll say useFetcher right here. And then to get the data that this Fetcher is going to be interacting with to be fully typed, I'm going to say typeof loader. So there's my loader right there. I get type safety for my Search Customer Fetcher. And that Search Customer Fetcher is going to have a dataproperty on it. And if that dataproperty exists, it may not. Because on the initial render, we're not calling this loader right from the start.

5. Handling Undefined Data in TypeScript#

Short description:

We're calling it when the user is searching, right. If there is no data, then that's undefined. If there is, we'll have customers. So our customers will be an array. Now TypeScript is happy, and our selected customer has the correct type.

We're calling it when the user is searching, right. And so if there is no data, then that's going to be undefined. But if there is, then we're going to have customers. So we'll have data Elvis Operator Customers. And if that doesn't exist, then we'll have that, those customers be an empty array. And with just that change, now a TypeScript is a lot happier. Because this type definition right there, our customers is going to be an array of customers. And now this type is correct. And so our selected customer is going to have a correct type. And the type we passed along to use combo box.

6. Making the Fetch Request#

Short description:

We need to make a fetch request whenever the input value changes. Downshift provides an API for detecting these changes. The Search Customer Fetcher has options for making the request. We'll use the submit option, which makes it easier to serialize query params. We'll handle the case when the query is undefined by assigning an empty string.

So that's really cool to be able to have full type safety across the network for a component that's going to be used all over the application. Who knows where it's used? So the last piece of this is actually making the request. And for us to actually make this fetch request, we just want to make a request whenever the input value changes and downshift provides this API for us to know when the input value changes. And so what it will say is the Search Customer Fetcher. And there are a couple of options on here. We have .form, which we could use if this was an explicit submission that the user is clicking on a submit button. That's not the case for us. This is an imperative mutation or an imperative query that we need to make as a result of some other user interactions. So we can't use form. There's also load, which we can use to make a GET request with query params, but we have to serialize those ourselves. So I don't want to do load, I'm going to do submit just because this makes it a lot easier to serialize those query params. And actually, GitHub Copilot is pretty close here. This is complaining right here because the query can only be a string, it can't be assigned undefined, an input value on the changes that were given is optional. It may not be there. So we'll just add a, I forget what that syntax is called, coercion or something, something there. If int value is null or undefined, then we'll end up with an empty string.

7. Adding the Get Method and Rendering the Component#

Short description:

We implemented the method as a get, but it could be an action. The action URL is for the loader inside resources/customers.tsx. We can use this component anywhere in our application and it will stay connected to the loader. We'll use it in the sales invoices new route to choose a customer for a new invoice. Importing from the routes directory is usually not recommended, but this is an exception. The functionality currently works, and we can fix the spinner.

Now the last piece we need to add to this is we need a method of get, or lowercase get here. And that is the case because we have implemented this as a loader. Now we could actually implement this as an action and have our method be really anything but get, like a post or a put or something, but I'm happy with this being a get. And then, um, and like for query endpoints, that's typically it makes most sense to be a get, but yeah, you do you, however you want to.

The cool thing is that you don't have to jump into 30 different files or multiple repos to make this change, you can just one day decide, you know what, I want to do this as an action instead and just switch it right here in the same file, which I think is rad.

Okay. And then the last thing is the action. Now this action is the URL that is going to be hit with this query. And the URL is the URL for this loader, which we've already established is inside of resources, customers, TSX. And so we're going to say slash resources, slash customers. Okay. And that's it, we have finished this feature. And it totally works. But we need to actually render this component. And this is this is the pretty cool part. So like, so far, this kind of feels a little bit just like your typical remix route and everything because you've got your loader, you've got your type of loader, like everything feels very similar to what you're used to in building a remix route. But the cool part is that we can actually use this component in anywhere in our application and it will stay connected to this back in loader. So in particular, the part of the application we want to use it in is inside of our sales invoices new when we're creating a new invoice so we can choose which customer we want. And so if we come down here, we've already got Cody helping us out with the props that we need to pass and everything. So we've got our customer combo box, which we are going to be importing from routes, resources, customers. So typically, I don't recommend doing any imports from the routes directory. In general, I just think that is not a really safe way to do things. But this is one exception that I think is totally legit and it is totally awesome. So that's all that we're going to do in the customer combo box piece here on the new route. And with that in place, if I come back here and go create new invoice, then I've got my customer combo box. Now, we currently have this set to true, and we can fix that here in a second. But the cool thing is that this functionality currently totally works as I make changes and I can select customer and all of that stuff. So that's pretty rad. We've got a component that is connected to its backend and all in a single file. So the last thing I want to do is fix the spinner because that is bothering me.

8. Implementing Spinner and Backend Connection#

Short description:

The pending state is determined by the SearchCustomerFetcher.state. If the state is not idle, the spinner is shown. To avoid a flash of loading state, a delay is added using the useSpinDelay package. This ensures a smooth transition and provides a nice pending state for users. The component can be rendered throughout the app, connected to the backend. It can also be packaged as an npm package for easy integration with other projects.

And so if we come down here, we've got our show spinner, and our pending state is going to come from our fetcher. So we'll have our SearchCustomerFetcher.state. And the state can be idle, loading, or submitting. Pretty much if it's loading or submitting, we know that we're in a pending state. Normally, I just determine whether we're in a pending state by saying, is the state not idle? If it's not idle, then we're pending.

There is a subtle difference between submitting and loading, where loading is going to get some data, submitting is when the user is submitting data. But in our case, I think it's reasonable just to say if the state is not idle, then we can show the spinner.

So with that in place now, we can see that there's no loading state. But if you watch carefully, you might actually see a flash of loading state, and that is not awesome. So there are a couple options here. You can add a like a transition delay or something. But the problem is if the request takes like within 50 milliseconds of whatever transition delay you put in there, you're going to get a flash of loading state. It's really basically impossible to avoid without a little bit of extra help.

So basically what we need is to say don't show the loading state unless you know… well let's put a delay in because that does make sense. If it's within 100 milliseconds don't show any loading state at all. But if I do show any loading state, then we should keep the spinner hanging around even if it's finished. So keep the spinner hanging around for another like 300 milliseconds or something like that just so that we don't have a flash, because it's way better to show it for longer than you need it than to just show a flash of loading state. And there's a package built specifically to solve this problem. It's actually built for my website by Stefan Meyer who helped with implementing my website. And it's called useSpinDelay. And we'll pass that along there. It has some good defaults we'll just keep those. And with useSpinDelay from the spin delay module, now we're going to avoid that flash of loading state. And if we do have a slow 3G network, then we are going to get a nice pending state, which is exactly what our users would expect. So with that in place, we're solid. This is really, really great. You could render this component all over the app and be certain that it is connected to its backend. On top of this, you could actually also package this up in an npm package and then expose just a couple of things for people to go into the Remix config, add their routes option here, and they call into your things so that you can hook up the route for the API route. And then they can just start using your component and it's all magically connected to the backend, which that's pretty interesting. And I'd love to see somebody try to do that.

9. Wrapping Up and Resource Routes#

Short description:

Remix allows us to create resource routes by simply having a route with no default export. We can export anything we like as long as it's not a default export. This co-location of code makes it easier for us to maintain the software in the long term.

So with all of that said, let me wrap up with a last couple of thoughts. So in review, Remix allows us to create resource routes by simply having a route with no default export. That's what makes a resource route. We can export anything we like as long as it's not a default export. So other components and utilities that integrate with the resource route directly. And so it's not just components. You could do hooks, you could do really anything like a button that links to a PDF generator and the loader is like generates the PDF, whatever. Anything that ties specifically to this resource. And just keep that co-location and that code co-location makes it easier for us to maintain the software in the long term. It's really, really cool and exciting. I love this.

QnA

Speaker's Gratitude and Favorite Remix Feature#

Short description:

The speaker expresses gratitude towards the audience and thanks them. The speaker mentions being excited to be at RemixConf EU and part of the community. They discuss their favorite Remix feature, Mutations, and how it simplifies application state management. The speaker refers to a poll where one of the favorite features was Kent. The speaker then transitions to the first question about whether full stack components break separation.

So the last thing that I want to say to you all is you're inspiring. Thank you very much. See ya.

Hello, thank you so much for having me. I'm super excited to be here. RemixConf EU rocks! That's sad. Super just happy to be a part of this community.

Yeah, it's awesome to have you here and that presentation was excellent. So the first question before we start is actually for you. And I wanted to ask, what is your favorite Remix feature? My favorite Remix feature? I chose Mutations. I think that application state management is the hardest part of building a web app these days. And Remix makes that a non-issue, completely. So that's my favorite feature for sure. That's awesome. When we did the poll on Slido, one of the favorite features was Kent. So I thought that was quite appropriate. It was pretty awesome. So we'll start with the questions. We'll start with the first one. Does full stack components break separation? Oh, yeah. Oh my gosh. I asked you your question. I completely forgot that we asked that. We asked the question beforehand that you provided. See how excited I am to talk to you, Kent? I better remember that there's other people that also want to ask questions. But before we do that, you asked the question, which was which one of these is not an accepted Remix export? And you had a couple of different options. And it looks that majority of people chose should revalidate. It was like 78%. Some people thought it was handles. Some people thought it was headers.

Full Stack Components and Separation of Concerns#

Short description:

Should revalidate in Remix is called as an unstable API, and it's called should reload. The Remix team is currently moving the React router APIs back into Remix. And so eventually, it will be should revalidate. But right now, it's unstable should reload. Full stack components break the traditional separation of concerns. JSX started breaking the idea of not mixing logic with markup. UIs require logic and design, so the concern is the combination of all these technologies. CSS and JS, Tailwind, and the backend are all part of the concern.

And a few people thought it was links. So what is the correct answer Kent? Yeah. Most people got it correct. This is a bit of a trick question because should revalidate in Remix is called as an unstable API, and it's called should reload. Unstable should reload. But in react router version 6.4, it's called should revalidate. And they're, the Remix team, is currently moving the React router APIs back into Remix. And so eventually, it will be should revalidate. But right now, it's unstable should reload.

That's awesome. And again, remember to go to Slido to participate in these questions that we're going to ask throughout the show. And that was a reminder for myself, by the way. And let's get back to questions with Kent. And let's go to the first one. Doesn't full stack components break separation of concern? Yeah, yeah. That's a good question. So, we've been breaking the people's idea of what separation of concerns means for years. Starting primarily, or at least in the modern age, started with JSX. And people saw JSX and they said, I shouldn't mix my logic with my markup. It just doesn't make any sense. Well, the fact is that we're working in UIs, and the logic is a very important part of what you're trying to accomplish. So, to me, that is the concern. The concern is the Twitter like button, or whatever it is that you're building. Twitter like button is a good example though, because it's not just the logic behind whether or not it's toggled on and off and what to do when the button's clicked, but it's also like what the thing looks like. So, then we've got CSS. That's a part of that too. So, now the concern includes all three of those technologies. So, that was my argument for CSS and JS, and now I'm into Tailwind, which is kind of a different take on that. But just the co-location of what concerns that use case. But then even that isn't the complete use case covered, right? There's also the back-end portion of that.

Fullstack Components and Island Architecture#

Short description:

Fullstack components embrace the fact that things that change together should stay together, redefining separation concerns. The idea emerged during the Remix advanced workshop for Remix Conf. Ryan initially liked the idea, and it has gained popularity. Full stack components are not the same as island architecture, as they focus on code organization and maintainability rather than performance optimization. They provide a cohesive environment for colocating code that should live together.

So, Fullstack components just takes that idea further, and really, my optimal code organization strategy is the things that change together should stay together. And so, if you're changing the back-end code anytime you change the front-end code, and vice versa, well, maybe you can put those things together. And if you're changing two things together frequently, then maybe they are the same concern. And so, yeah, it doesn't break separation concerns. It embraces the fact and maybe redefines what separation concerns means in your mind.

Yes. So, where it came from for me was I was working on the Remix advanced workshop for Remix Conf in the U.S. and I was building a combo box showing how to use use Fetcher and everything. In fact, like the the one that we did today, the exact same example. And I had them in several... So I had a resource rounded over here and then I had my component over there and I was like, I wonder if I could just... and then like, sure, I guess why not? And I showed it to Ryan because he was going to co-present that workshop with me. He's like, I don't hate it. And let me think about that for a little while. And then eventually he decided he really liked it. I love it. And so, yeah, just it's definitely not something that the Remix team had ever really thought about. But I am seeing this and I love it. Now, that's awesome. That's awesome.

Another question we have, KB says, I've been hearing the term island architecture recently from other JS frameworks. Are these full stack components like Remix's version of that? Not exactly. Island architecture is a lot more about what gets hydrated and where. And in Remix apps, it's all still the entire thing is hydrated. And so it is a little different. You might be able to implement a sort of islands architecture possibly this way. Yeah, people do wild things with resource routes. But yeah, this is more it's less about a thinking like a performance optimization, and more about a maintainability optimization and colocating the code that should live together. It definitely feels like you're in an island though, because I mean, your component can accept props and everything.

Full Stack Components and NPM Publishing#

Short description:

Full stack components allow for a great way to develop components that can accept props, reference context, and combine backend and frontend code. They can be published to NPM by either creating a route file and calling functions in an NPM module or by publishing a function to be called in the REMIX config. Hydrating specific routes in REMIX can create islands, but it may not align completely with the concept of island architecture.

It definitely feels like you're in an island though, because I mean, your component can accept props and everything. It can reference context and stuff. But it really does feel like it's on its own little island. And it has its back end and front end and everything all just together. It's just a really great way to develop those types of components.

Nice, nice. And another question. Can full stack components be published to NPM? That's a great question too. So yes, they can. So the challenge is, you've got a single file. And with REMIX, there is a file convention. And so how do you, like if I wanted to make a Twitter like button that people can use on all of their different websites, how would I do that as a single file component? Because we need to have a file in the routes directory for a resource route. Well, that's not completely true because you can actually imperatively at build time create routes in REMIX config. There's a routes option there. And so you've got two options. You could make a route file and then just call into functions in an NPM module that handles everything for you and you just tell it what's the resource route URL. Or you could publish a little function that people are supposed to call in their REMIX config. And so in the REMIX config, we say like, set up my Twitter like button route thing. And so then that way, the Twitter NPM module would be able to know what the URL for the resource route is, because it's responsible for creating that resource route. And then it can talk to itself that way. So I haven't seen anybody do this, but I think that'd be cool if somebody did.

No, awesome. Awesome. To follow up on the island architecture question, couldn't you only hydrate specific routes and REMIX to make it islands? So, yeah, I wouldn't. Yeah, I'm sure that is possible. It's not something that I've tried. But, I wouldn't call that– Islands to me is like many things on a single page. We do have the idea of nested routes, and so maybe you can have a nested route that this is the only part that's hydrated. I'm not gonna say that island architecture isn't in line with what REMIX is trying to do. I'm not completely convinced that the– Though like it is technically, from a theoretically technical standpoint, it is better to run less code.

Island Architecture and REMIX's Suitability#

Short description:

I'm not convinced that the island architecture is always the right thing. I use REMIX for everything. There are very few projects that REMIX isn't well-suited for. REMIX doesn't have HMR yet, but the team is working on it. Starting with REMIX allows you to adapt to changing requirements better than anything else. REMIX being part of Shopify is thrilling, as it provides stability and funding for the framework.

But in practical terms, I'm not convinced that the island architecture is always the right thing. And even necessary for most apps. And so that's why I haven't really spent a whole lot of time thinking about or working through that myself. But I am convinced that you could implement an islands architecture with REMIX but yeah, I haven't bothered to try.

Yeah, no thank you for that. This is a question I wanna ask because I know there's a lot of people that haven't tried REMIX yet. So are there any projects that you wouldn't use REMIX for or what is your thought on that?

Yeah, no projects that I wouldn't use REMIX for. I use REMIX for everything. So there are very few projects that REMIX isn't well-suited for. I have talked to some teams that are like, well, we just can't do life without HMR. It's like, well, I mean, okay. REMIX doesn't have HMR yet. Eventually, we'll get that, but it doesn't. Things are a little bit unique because REMIX is so server-centric, like how do you do HMR with the server and stuff, but I'm convinced that the team is eventually going to figure out something for that. But like just about anything else I can think of, like you think, okay, well, what if I have a single page? It's a game, it's using local storage for everything. Why would I use REMIX for that? I mean, yeah, you're not going to take advantage of nested routing, that sort of thing. You're not taking advantage of loaders necessarily. But what else are you going to use that's going to be any better? Like, will Veep serve you better? Not really. Like, it's like we're all kind of on the same playing field. And what's cool about starting with REMIX is that eventually when you decide, oh, man, this game is wordle and I'm about to sell to like this big company or whatever, and we need data persistence and you know... Well, you just upgrade to that because you built it with REMIX from the start. And so I struggle to see situations where REMIX isn't a great starting point because it allows you to adapt to changing requirements better than anything else I've seen.

Nice. Cool. And here's another great question. How do you think REMIX being part of Shopify will affect the framework? Oh, my gosh. I'm so, so thrilled about this Shopify thing. Like just imagine for a moment that REMIX had not sold to Shopify, REMIX is doing, is still doing fine. Like we would have continued to work just fine for like another year and a half or so on the funding that we'd received originally with the number of employees we had. So like it would have been fine but the problem is eventually the REMIX team would have to figure out a way to make money.

Shopify's Acquisition and the Future of REMIX#

Short description:

Shopify's acquisition of REMIX allows the developers to focus solely on the framework's development without distractions. This partnership ensures that REMIX version two will be released sooner, benefiting the community. Shopify's unique requirements make them an ideal acquisition company, providing a solid foundation for a framework. Their collaboration promises exciting use cases and a positive future for REMIX.

And what all that means is that these amazing developers who are developing this framework for us would be distracted by other things that are not related to what the framework is. And so Shopify coming in just says, hey, you keep on working on what you're doing, you're doing a great job with that and we'll take care of the money thing. And so I'm thrilled that Ryan and Michael in particular don't have to worry about the making money stuff and they just continue churning on this framework for us. I think I'm convinced that we're gonna get REMIX version two much sooner than we would have if they had to start thinking about making money. So I'm thrilled and of all of the companies to acquire REMIX, I think Shopify is just so good as an acquisition company because they have some of the most interesting requirements that I don't think are generally applicable to everybody but definitely it's a really good baseline or a common denominator for what people need out of a framework. So really excited about the use cases that Shopify will bring to bear on REMIX. And I think, and they've just been really awesome as a company too. So I think that they're gonna be really great stewards of the web and a really great place for REMIX to hangout.

Speaker's Love for REMIX and Shopify's Support#

Short description:

I fell in love with REMIX instantly. Shopify's support increases confidence and adoption. REMIX is my go-to for personal projects, enabling faster development.

Yeah, no, that's really, really awesome. The soon as I tried REMIX, I fell in love with it instantly. And a lot of times when I show REMIX to others, they're like, wow, this is a really cool way of doing it. And I think having a company like Shopify stand behind REMIX is huge because it gives more confidence for someone to be like, hey, this is backed by Shopify, let me check out this and it'll increase the adaptation rate. But for me, like I said, for all my personal projects, REMIX has been my go to way of doing things. And I find myself developing things faster, which is pretty awesome.

Influences of Hydrogen on REMIX#

Short description:

The REMIX team discussed the influences of hydrogen towards REMIX with Shopify. They compared server components to Remix's current capabilities and found Remix to be a better approach. Shopify decided to bring the Remix team on board. Hydrogen's role will likely involve more full-stack components, such as a configurable shopping cart. The end game is still unclear, but there may be a hydrogen stack or a special CLI. Hydrogen concepts are not expected to be integrated into Remix, as Remix already has similar functionality. However, Shopify engineers will contribute to Remix's development.

And I guess like another question I have, do you think there's going to be influences from hydrogen towards REMIX? Yeah, actually, so the REMIX team, we talked to Shopify months ago, like even before REMIXconf. They came out to Salt Lake, we were talking about, you know, potentially doing what they're doing now earlier before they released hydrogen with the server components. And we're just trying to say, hey, listen, like server components aren't really released yet. Like it's not a stable API or anything. Like you're going to release on top of something that's not finished. But look at what we have now. So like compare what server components gives you maybe in the future to what Remix gives you today. Now, absolutely. And we just think that this is a better approach. And so eventually Shopify took that to heart and decided that they really wanted the Remix team and brought us over or I'm not there anymore. Just let them to be clear. I'm full-time on Epic web, but decided to bring the Remix team over. And I think that hydrogen's role will be more full-stack components. Type of situations, they'll have like a shopping cart that you bring in and maybe configure. It could be like, they had the blog post where you still are using hydrogen, but you're importing things from Remix. So there's kind of like a mix there. I'm not sure what the end game for that is. Like, do you install Remix? And then, or maybe there's a hydrogen stack sort of thing. I think that probably makes a lot of sense to have a hydrogen stack. I expect that's probably something that will come out of that, whether it's technically a stack or maybe some special CLI that the hydrogen team comes up with. But as far as like hydrogen concepts coming into Remix, I don't see anything like that. There doesn't seem to be anything that hydrogen specifically had that Remix didn't already have outside of things that are Shopify specific, like shopping cart and stuff, which of course wouldn't be well placed inside of a generic framework like Remix. But certainly, there are a lot of really smart engineers at Shopify who will absolutely be helping Remix in lots of ways. So I'm looking forward to that collaboration too.

Full Stack Components and State Management#

Short description:

In Remix, there is no need for state management libraries like Redux. The framework works without JavaScript and embraces the concept of progressive enhancement. Using application state management would hinder progressive enhancement. While it's technically possible to use Redux with Remix, it's not recommended as the framework doesn't require it.

No, that's awesome. That's awesome. And we have a question from Peter Horn, she, her asks, are full stack components meant to be replacements for state management libraries, like Redux or complements? Yeah, so actually, in Remix, there aren't really state management, application state management libraries needed at all. There is no application state management. That's evidenced by the fact that it works without JavaScript, but also required by the idea of progressive enhancement. So if you're focused on progressive enhancement, then you can't use application state management. If you do, then your app doesn't progressively enhance, I call that a bug. And so like, while you technically can use Redux and those things with Remix, I strongly advise against it for that reason. And so full stack components aren't like a replacement. They certainly could work with those things, but yeah, I wouldn't bother using them because you don't need them with Remix.

Kent C. Dodds
Kent C. Dodds
37 min
18 Nov, 2022

Comments

Sign in or register to post your comment.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Building Better Websites with Remix
React Summit Remote Edition 2021React Summit Remote Edition 2021
33 min
Building Better Websites with Remix
Top Content
Remix is a web framework built on React Router that focuses on web fundamentals, accessibility, performance, and flexibility. It delivers real HTML and SEO benefits, and allows for automatic updating of meta tags and styles. It provides features like login functionality, session management, and error handling. Remix is a server-rendered framework that can enhance sites with JavaScript but doesn't require it for basic functionality. It aims to create quality HTML-driven documents and is flexible for use with different web technologies and stacks.
Don't Solve Problems, Eliminate Them
React Advanced 2021React Advanced 2021
39 min
Don't Solve Problems, Eliminate Them
Top Content
Kent C. Dodds discusses the concept of problem elimination rather than just problem-solving. He introduces the idea of a problem tree and the importance of avoiding creating solutions prematurely. Kent uses examples like Tesla's electric engine and Remix framework to illustrate the benefits of problem elimination. He emphasizes the value of trade-offs and taking the easier path, as well as the need to constantly re-evaluate and change approaches to eliminate problems.
Scaling Up with Remix and Micro Frontends
Remix Conf Europe 2022Remix Conf Europe 2022
23 min
Scaling Up with Remix and Micro Frontends
Top Content
This talk discusses the usage of Microfrontends in Remix and introduces the Tiny Frontend library. Kazoo, a used car buying platform, follows a domain-driven design approach and encountered issues with granular slicing. Tiny Frontend aims to solve the slicing problem and promotes type safety and compatibility of shared dependencies. The speaker demonstrates how Tiny Frontend works with server-side rendering and how Remix can consume and update components without redeploying the app. The talk also explores the usage of micro frontends and the future support for Webpack Module Federation in Remix.
Understanding React’s Fiber Architecture
React Advanced 2022React Advanced 2022
29 min
Understanding React’s Fiber Architecture
Top Content
This Talk explores React's internal jargon, specifically fiber, which is an internal unit of work for rendering and committing. Fibers facilitate efficient updates to elements and play a crucial role in the reconciliation process. The work loop, complete work, and commit phase are essential steps in the rendering process. Understanding React's internals can help with optimizing code and pull request reviews. React 18 introduces the work loop sync and async functions for concurrent features and prioritization. Fiber brings benefits like async rendering and the ability to discard work-in-progress trees, improving user experience.
Debugging JS
React Summit 2023React Summit 2023
24 min
Debugging JS
Top Content
Watch video: Debugging JS
Debugging JavaScript is a crucial skill that is often overlooked in the industry. It is important to understand the problem, reproduce the issue, and identify the root cause. Having a variety of debugging tools and techniques, such as console methods and graphical debuggers, is beneficial. Replay is a time-traveling debugger for JavaScript that allows users to record and inspect bugs. It works with Redux, plain React, and even minified code with the help of source maps.
Making JavaScript on WebAssembly Fast
JSNation Live 2021JSNation Live 2021
29 min
Making JavaScript on WebAssembly Fast
Top Content
WebAssembly enables optimizing JavaScript performance for different environments by deploying the JavaScript engine as a portable WebAssembly module. By making JavaScript on WebAssembly fast, instances can be created for each request, reducing latency and security risks. Initialization and runtime phases can be improved with tools like Wiser and snapshotting, resulting in faster startup times. Optimizing JavaScript performance in WebAssembly can be achieved through techniques like ahead-of-time compilation and inline caching. WebAssembly usage is growing outside the web, offering benefits like isolation and portability. Build sizes and snapshotting in WebAssembly depend on the application, and more information can be found on the Mozilla Hacks website and Bike Reliance site.

Workshops on related topic

Master JavaScript Patterns
JSNation 2024JSNation 2024
145 min
Master JavaScript Patterns
Top Content
Featured Workshop
Adrian Hajdin
Adrian Hajdin
During this workshop, participants will review the essential JavaScript patterns that every developer should know. Through hands-on exercises, real-world examples, and interactive discussions, attendees will deepen their understanding of best practices for organizing code, solving common challenges, and designing scalable architectures. By the end of the workshop, participants will gain newfound confidence in their ability to write high-quality JavaScript code that stands the test of time.
Points Covered:
1. Introduction to JavaScript Patterns2. Foundational Patterns3. Object Creation Patterns4. Behavioral Patterns5. Architectural Patterns6. Hands-On Exercises and Case Studies
How It Will Help Developers:
- Gain a deep understanding of JavaScript patterns and their applications in real-world scenarios- Learn best practices for organizing code, solving common challenges, and designing scalable architectures- Enhance problem-solving skills and code readability- Improve collaboration and communication within development teams- Accelerate career growth and opportunities for advancement in the software industry
AI on Demand: Serverless AI
DevOps.js Conf 2024DevOps.js Conf 2024
163 min
AI on Demand: Serverless AI
Top Content
Featured WorkshopFree
Nathan Disidore
Nathan Disidore
In this workshop, we discuss the merits of serverless architecture and how it can be applied to the AI space. We'll explore options around building serverless RAG applications for a more lambda-esque approach to AI. Next, we'll get hands on and build a sample CRUD app that allows you to store information and query it using an LLM with Workers AI, Vectorize, D1, and Cloudflare Workers.
Remix Fundamentals
React Summit 2022React Summit 2022
136 min
Remix Fundamentals
Top Content
Featured WorkshopFree
Kent C. Dodds
Kent C. Dodds
Building modern web applications is riddled with complexity And that's only if you bother to deal with the problems
Tired of wiring up onSubmit to backend APIs and making sure your client-side cache stays up-to-date? Wouldn't it be cool to be able to use the global nature of CSS to your benefit, rather than find tools or conventions to avoid or work around it? And how would you like nested layouts with intelligent and performance optimized data management that just works™?
Remix solves some of these problems, and completely eliminates the rest. You don't even have to think about server cache management or global CSS namespace clashes. It's not that Remix has APIs to avoid these problems, they simply don't exist when you're using Remix. Oh, and you don't need that huge complex graphql client when you're using Remix. They've got you covered. Ready to build faster apps faster?
At the end of this workshop, you'll know how to:- Create Remix Routes- Style Remix applications- Load data in Remix loaders- Mutate data with forms and actions
Developing Dynamic Blogs with SvelteKit & Storyblok: A Hands-on Workshop
JSNation 2023JSNation 2023
174 min
Developing Dynamic Blogs with SvelteKit & Storyblok: A Hands-on Workshop
Top Content
Featured WorkshopFree
Alba Silvente Fuentes
Roberto Butti
2 authors
This SvelteKit workshop explores the integration of 3rd party services, such as Storyblok, in a SvelteKit project. Participants will learn how to create a SvelteKit project, leverage Svelte components, and connect to external APIs. The workshop covers important concepts including SSR, CSR, static site generation, and deploying the application using adapters. By the end of the workshop, attendees will have a solid understanding of building SvelteKit applications with API integrations and be prepared for deployment.
Back to the Roots With Remix
React Summit 2023React Summit 2023
106 min
Back to the Roots With Remix
Featured Workshop
Alex Korzhikov
Pavlik Kiselev
2 authors
The modern web would be different without rich client-side applications supported by powerful frameworks: React, Angular, Vue, Lit, and many others. These frameworks rely on client-side JavaScript, which is their core. However, there are other approaches to rendering. One of them (quite old, by the way) is server-side rendering entirely without JavaScript. Let's find out if this is a good idea and how Remix can help us with it?
Prerequisites- Good understanding of JavaScript or TypeScript- It would help to have experience with React, Redux, Node.js and writing FrontEnd and BackEnd applications- Preinstall Node.js, npm- We prefer to use VSCode, but also cloud IDEs such as codesandbox (other IDEs are also ok)
How to Solve Real-World Problems with Remix
Remix Conf Europe 2022Remix Conf Europe 2022
195 min
How to Solve Real-World Problems with Remix
Featured Workshop
Michael Carter
Michael Carter
- Errors? How to render and log your server and client errorsa - When to return errors vs throwb - Setup logging service like Sentry, LogRocket, and Bugsnag- Forms? How to validate and handle multi-page formsa - Use zod to validate form data in your actionb - Step through multi-page forms without losing data- Stuck? How to patch bugs or missing features in Remix so you can move ona - Use patch-package to quickly fix your Remix installb - Show tool for managing multiple patches and cherry-pick open PRs- Users? How to handle multi-tenant apps with Prismaa - Determine tenant by host or by userb - Multiple database or single database/multiple schemasc - Ensures tenant data always separate from others