Combine the power of the old and new web with Remix!
Modern web development has given us a cornucopia of powerful abstractions. But as we've moved to higher levels of abstraction Ryan has noticed that we are reinventing the wheel in places, especially with what the browser provides by default.
Remix aims to solve this problem. Remix is trying today's benefits of a highly dynamic page, but still have that same feeling of simplicity that we had with PHP.
As you use Remix what ends up happening is that you accidentally become a better web developer as become a lot more familiar with the browser's abilities.
Spend an hour or two reading the MDN docs on HTTP
Kent C. Dodds (00:00):
Hello friends. This is your friend, Kent C. Dodds and I am joined by my friend Ryan Florence. Say hi, Ryan.
Ryan Florence (00:05):
Kent C. Dodds (00:06):
Oh, good one. Yes.
Ryan Florence (00:08):
How many people made that stupid joke?
Kent C. Dodds (00:10):
No, it's perfect. The entire season I've been making that joke and three people got it. So, good job. So, Ryan and I have known each other for a long time. We were both in Utah. He left for a while but he's back. And we met, I think, for the first time at a meetup. I think it may have... Was it an Angular JS meetup? I don't know.
Ryan Florence (00:34):
My memory was, it was my first React workshop I ever did and you were in the front row.
Kent C. Dodds (00:39):
Yeah. Well, I remember... I feel like I met you before that.
But in any case we... because I remember standing in parking lots after meetups chatting with you and-
Ryan Florence (00:49):
I never went to a single Angular meetup so it wasn't that.
Kent C. Dodds (00:51):
Yeah. It must've been a React meetup then.
Ryan Florence (00:53):
We did the Utah JS things too.
Kent C. Dodds (00:55):
Ryan Florence (00:56):
Probably one of those.
Kent C. Dodds (00:57):
This was back in 2014, 2015 timeframe, right when I started getting into React at the end of 2015. Well, sorry. I started working in React at the end of 2015. I started playing with React in 2015, but you were much earlier... Well, right. You were much earlier in the beginnings of React, 2014, maybe 2013. Is that right?
Ryan Florence (01:21):
I ignored it for a year. I was putting all my bets on Ember. But anyway, switched to React. It'd been out for about a year when I really started looking at it because we were hitting some major performance issues in her app and React solved them.
Kent C. Dodds (01:40):
It was a miracle. And early on, you gave the talk that ... I can't pronounce it. But what was it like reacting Angular?
Ryan Florence (01:50):
Embularactymerbone. It was a JS comp 2014. That was right in the middle of my transition just a few months earlier. I had been speaking at Ember column about Amber components, and what you could do with them, and how they can encapsulate state and talk to each other through events and all this stuff, which is basically a talk about React in Ember. But I didn't know it at the time. I hadn't even touched React yet. And then right after that talk, I started goofing around with React and I was like, "Oh boy, this is exactly what I've been wanting out of these components." And yeah, anyway, they asked me at JS comp to give a talk on all of the frameworks, kind of compare them all. And so, yeah. Embularactymerbone. Ember, Angular, React, Polymer, Backbone.
Kent C. Dodds (02:42):
I missed the Polymer in that title. But yeah, that's great.
Ryan Florence (02:46):
That's the mer part. Embularactymerbone.
Kent C. Dodds (02:49):
Oh, there you go. Cool. [crosstalk 00:02:52]. Yeah. I had a slightly similar experience with Angular JS where I made directives like as one does. I spent most of my time making directives that were basically components. This was before Angular.component was a thing. And that was just what I wanted. And so, when I started playing around with React, it was very much like, "Oh, okay." So, this is-
Ryan Florence (03:17):
This is what I was chasing.
Kent C. Dodds (03:19):
Ryan Florence (03:46):
Sure. Hobbies. I grew up playing soccer, snowboarding, skateboarding, wakeboarding, anything on a board. It was fun. Actually, wrote in some wakeboarding tournaments and stuff. I wasn't a pro or anything, but I could do flips and stuff. Not anymore. I'm too old. That stuff hurts when you wreck. Gave myself a few concussions. So now, I always have a helmet on no matter what I'm doing. And then, played a lot of music, played in some bands, recorded some CDs. I bring in the music because music, I feel, has a huge influence on my coding and what I enjoy most about writing code. And that's the composition of it all, how you put a song together, how does the melody match with the chorus, and when did these instruments come in, and all that kind of stuff. And code to me feels a whole lot like writing the song.
Yeah. So I was a teenager, I was mid-nineties and I just built websites for my band, the bands that we played shows with, built everybody's websites. And that's why they let me play shows with them is I built their websites. And then, I did that for a bit. My dad invested in a what'd they call those, an ISP. Internet service provider. When you used to have to call with your modem and you'd take over the phone line. And then, you're trying to download a picture of Kurt Cobain playing live somewhere, and your mom picks up the phone and kills the connection, you're like, "Mom, no." I've been downloading this for 32 minutes. And then, yeah. He invested in one of those. And I started to build websites for them. They paid me $9 an hour, which back in the nineties, for a 15 year old, 16 year old, those was decent money.
So, yeah. And then, we had this thing called CGI bin and that's where you kind of think of that as API routes now. We call it an API route. That was your CGI bin. You could run scripts there. And then, I quit doing web stuff, went to college, studied economics, got a degree, went into retail, finance, insurance and junk. And then, somehow found my way back over to web development. And yeah, I worked for agencies doing credit card websites for Capital One and internal emails for Visa and just any kind of client work, and then got a job at Instructure who builds canvas LMS. And that's where I got a lot of my dev experience. Was working there for several years on a huge app. If you're familiar with Rails, you can type rake routes, and it will tell you all of the routes in the app. And there were about 2,500 routes in this app. So, it was a pretty large app.
Kent C. Dodds (07:26):
I used it. So, I know there's a lot to it.
Ryan Florence (07:30):
Kent C. Dodds (08:30):
No, that's awesome. Anybody who has been listening to the show or knows me at all knows that I am really looking forward to chatting with you about this because I just, I love Remix. I've been playing around with Remix since ... Well, even reading what you've been writing about it since you first got started.
Ryan Florence (08:51):
I left April.
Kent C. Dodds (08:52):
Yeah. So it's been a long time and it's just fantastic.
Ryan Florence (08:57):
You're excited about it before it was even for sale. Because if I remember correctly, you bought a ticket, or not a ticket. You bought a license before I even got to run through my testing the production website. I had no link to the buy page on the website, but I deployed it with no links. And I guess you just type in slash and buy it.
Kent C. Dodds (09:18):
Yeah. Somebody in my Discord shared the link and they're like, "Hey, look, you can buy it now." And, it was the day of, I think you were going to launch in 20 minutes when you [crosstalk 00:09:28].
Ryan Florence (09:27):
Yeah. I had just deployed it. And, I went and grabbed myself some breakfast. And then, I came back and I went through the little checkout flow to make sure that it really worked. And then, I was going to deploy again with the link on the homepage and people were already buying my test license for $1.
Kent C. Dodds (09:46):
Yeah. I still have that license on my dashboard.
Ryan Florence (09:49):
I know. I need to go. Yeah. So, when our customers log in to remix.run, they get their license key in there and it lists any license they have. So, there's a handful of people that all bought this funny $1 license.
Kent C. Dodds (10:03):
Ryan Florence (11:07):
And PHP was a lot that way. You had your web server on some web host that was running PHP. You didn't have a PHP server. You didn't initialize it or anything. It was just, you clicked a couple buttons. And it was like, "Okay, now I got a PHP server thing," and you could upload through FTP, file transfer protocol. You just put some PHP files up there and you could execute code. You can write logic to kick out HTML. You can go talk to a database, go ask your database for some data and then loop over that array and then echo out some HTML based on that data. It actually feels a whole lot like a React component, except for you wouldn't need use effect and stuff. Just at the very top, you can be like, go to the database, get some data. Okay. Now, map over this thing and then kick out some elements.
Kent C. Dodds (12:40):
Yeah. That's a single file component to the max.
Ryan Florence (12:44):
Yeah. And back when I was doing PHP for my own stuff, it was just like, I didn't have a whole lot of structure. I just put a file up there. That was my route. And at the top, I'd make my database query, top of the file. Underneath that, I'd iterate through all my data to kick out HTML. And then down at the bottom, I just put a script tag to add dynamic behavior to it. And then, if I had a form on the page, I would just post, form method post, and it would post to that very same file. And at the top of the file would ask if HTTP method is post. I think, it was dollar underscore post. If I had anything in the post, then, "let's go to the database and then redirect right back to this page." But if I didn't have a post up there at the top, then it was a get request. And so, I was just going to get the data and display it. So, I had all this stuff just in this one file. And a lot of us built stuff that way.
You asked how we got from there to where we are. I don't know. It's all sort of such a blur. It's [Ajax 00:13:59]. Ajax basically was invented by i6, 5, 6. It was 95 XML HTTP request for Outlook Express, an email client. This is my memory. It could be wrong. But, I remember learning this at some point that they were building Outlook Express. And instead of doing a full page reload to go and check your mail, because it's your email. You want stuff to show up as it arrives. The Microsoft team was like, "We want to wait to go and talk to the server without unloading this whole page." And so, they came up with XML HTTP request. So, that allowed the browser to say, "I'm just going to make a little request, not for this new document. I'm not going to change the URL or anything. I'm just going to go off to the server and ask for some information."
And today, you've got all these tricky bits of the user interacted, I need to go find some elements. I need to go change them and change the state of the UI. And now, they click something else and I need to go change this other piece of the UI. And, I hit this hard at a job that I had a long time ago, building. It was a microcontroller website. What was the company? [Atmill 00:17:02]. Atmill has a whole bunch of microcontrollers. And, we were contracted to build this, it's pretty normal now on websites. But back then, it was a pretty big deal. A little sidebar that had a whole bunch of filters on it like check boxes for what type of controller you want, how many pins it has.
And as you interacted with that thing, I needed to go make HTTP requests for data and then update the screen with those results. This is like, React 101 now. It's so easy, but it was dang hard before because we didn't, we weren't really programming in the browser with this idea of this state that drives the UI. You just had the UI. And when anything happened, you'd go and you'd grab pieces and delete them. And then, you'd build pieces and inject them. And you just cross your fingers and hope that you made the UI look the way you wanted it to look.
So, it was a lot of that kind of stuff happening. A lot of [dom 00:18:08] manipulation is what we call it and that got really hard. And so then, we got things like Backbone JS and Knockout JS that had this pub sub idea where you'd say, "Okay. Instead of in our click handlers going and grabbing pieces and manipulating them, let's just emit any event." We're going to have some other code that listens for that event and responds to it or reacts to it. That got tricky though, because you've got all these global topics or channels that you're broadcasting and it was hard to see where the code connected. And, the next generation that we saw was when Ember, and Angular, and React popped up. And instead of being dom manipulation or broadcasting events, you had this idea of state. You'd say, "Here is the state of my app."
And then, you would just inspect and iterate that state to kick out your HTML. Well, that sounds 10 minutes ago in this conversation. PHP. You'd go to the database, get your data. And then, you did your data and kick out your HTML. So now, we actually had that in the browser with these new frameworks where I've got this state. I got to go get it from somewhere, but I've got it. And now, I can just look at that state and kick out HTML. But, the framework is going to do the dom manipulation for me. And so, my whole career has felt like I started in this kind of, well, I started before PHP. I just did plain HTML, but when I really started programming real websites, not real websites, websites that had databases and had changing UI. I guess, more complex websites. I feel like I've been chasing that PHP dream the whole time and all the tools that I really enjoyed gave me that feeling.
Kent C. Dodds (22:01):
Ryan Florence (23:02):
They don't even know that a form can submit itself.
Kent C. Dodds (23:04):
Right. Yeah. They just learn events.prevent default. I don't know why I do that, but then I can do that stuff.
Ryan Florence (23:11):
Yeah. I'm going to go parse the form and I'm going to serialize it into something and I'm going to make a fetch. Well, forms already know how to do that all by themselves.
Kent C. Dodds (23:19):
Even when you were first getting started with PHP, HTTP understands these types of requests and you can make a form that makes this request, and not that we want to keep doing full page refreshes. There was a reason that Ajax was invented, but we can mesh these in a way that eliminates lots of the problems that these tools were built to solve so that you don't have to worry about solving them in the first place. And then, also it gives you the cool flexibility that you need for accessibility or that you want for a better, more dynamic web application.
Ryan Florence (24:52):
Totally. A good example of this is, it's right at the end of our Remix beta live stream that Michael and I did. We're kind of show at the very end. There's this common problem in a React app where you've got some data on the page on a sidebar. And then, you've got the main screen that has a button or a form or something on it that manipulates that data maybe to just ... In our live stream, it just added a task to a list. And on the left side, you got a list of all the projects and they have little counters next to them. How many tasks there are and how many are complete?
And that way, you have a form deeply nested inside of your UI. And then, you have data that it affects way outside of the top of your layout. That's going to get up to date without you having to do anything about it, because we just emulated what browsers do with forms and HTTP. And, it's kind of those things where it's just like, "Oh, whoa. This is way easier."
Kent C. Dodds (29:07):
Now I don't have to worry about caching.
Ryan Florence (29:10):
Yeah, you don't. That's the thing. You're bringing up React query and Apollo and stuff. A lot of the things that those tools do is they try to make sure I already have this data on the page. So on this next React tree, we called set state somewhere, right? Someone called set state. We asked for this data, and then these clients I tools are like, "Well, do I already have the data or not?" And now I'm going to only fetch the pieces that I need. Now, I need to expire all of those things because I may have just changed it.
In Remix, you just don't even have those problems because we emulated what the browser would do. And, we know all of your nested routes. When we use the word route, it's different than what a lot of people think of. So, layouts, all of your nested layouts, each layout can say, "I need this data down the whole tree." And we can look at that. We don't need something like a React query or Apollo to optimize our queries. We just know looking at the route and the layouts We go, "Oh, hey. You know what, this layout's not even changing, so we don't need to refresh that data." And this layout is not changing. So I don't need to refresh that data, but this layout did change. So, we're going to go and call the loader for this layout.
Kent C. Dodds (30:20):
As well as parents.
Ryan Florence (30:23):
Oh, not on a normal navigation. We don't fetch the parent. Yeah. We only fetch this [crosstalk 00:30:28] that's changing, which is why we don't need a big client side cache. It's just the pieces that we need. But, yeah. I think what you were thinking was then when you submit a form and we say, "Okay, let's recall everything because you might've changed something," but you don't have to worry about which keys do I need to expire? Which thing might've changed? We actually just had a customer this morning who was saying, "Hey, my route loader, the data never changes. It's always the same. It's just my environment variables like a Stripe ID." What is it? The striped public key and that kind of stuff.
And they're like, "It never changes, but Remix keeps fetching it whenever I submit a form." So he said, "Well, put a cache control header on that loader," which is an HTTP idea that browsers understand. You can tell a browser, "Hey, if you make this request, it's got a max age of an hour." So if my code tries to request this another time, just bring it from your own cache. Don't even make the request. So, your code still pretends like it's making the request, but the browser just pulls it from disk or from memory. And so, we have these tools. Yeah. We have these tools in it.
Kent C. Dodds (31:39):
[inaudible 00:31:39] going to gush over that. I just love that. Yeah. So, this is one of the things that I've really appreciate about Remix in general is just that it's forcing me to spend a lot of time on MTN. It's like, I have to learn about headers and I have to learn about request and response and HTTP to be able to use Remix effectively. And, when I created React testing library, that was one of the big appeals there too, was that, we didn't create a bunch of extra APIs for you to go learn. We don't have this special find by component name or any of this weird stuff. We just give you dom nodes and you do what you want with dom nodes. You want to learn how to interact with Dom nodes, go to the MDN docs.
Ryan Florence (33:00):
And you'll see if you use Remix that a lot of the code, like you just said, you're on MDN a lot, looking at how URL search parameters work, or how request and response objects that you get back from fetch. What are those? Because that's our primitive for HTTP is the web request model that we got with fetch. We want to keep it close enough to the platform that when you learn Remix, you accidentally learn how to be a better web developer. Stuff you might think is something specific to Remix like a cache control header or the response object or request object. They're actually not Remix. They're just the web. They're just HTTP. And so, that's a goal of ours. Get good at Remix, accidentally get good at web development, generally.
Kent C. Dodds (36:32):
I love that. And, we're overtime so we can't go on, but there are so many things I'd love to go on about, like talking specifically about some of the trade-offs that you made with Remix and the way that you built it. But we'll have to talk about that another time. So, for our homework for today, Ryan just wants you to get better at building websites and in particular with the foundations of the web. And so, the homework for you is to spend an hour or two reading the MDN docs on HTTP. That's the Mozilla developer network, if you've unfamiliar with that. And, we'll have a link to that in the notes. Ryan, it's been awesome chatting with you. What's the best place for people to keep up with what you're up to?
Ryan Florence (37:20):
Just Twitter, Ryan Florence.
Kent C. Dodds (37:23):
Sweet. And, we'll have a link to that too. All right. Thanks, Ryan. This has been awesome. And thanks everybody for listening. We'll see you later.
Ryan Florence (37:29):