Current section: Optimizations 29 exercises
lesson

Intro to Optimizations

Loading lesson

Transcript

00:00 Let's talk about a couple of optimizations that we can make in our application. And the first one is about waterfalls. So we've got some waterfalls in our app. This is what a waterfall looks like. So specifically, this is the stair cascading kind. At least that's what I call it.

00:18 Technically, what you see in the network tab right here, this is called a waterfall, and it doesn't have to be a stair cascade like this one. It can be more like Niagara Falls like this. Or actually, I grew up next to Shoshone Falls, which is taller than Niagara Falls. Maybe not as big, but it is taller.

00:36 So you'll notice if we look at our UI, we've got kind of a cascade going on here where it starts here, and then once that data is loaded, now it can load this data. And as we're navigating between these different ships, we see a bit of a cascade going on there too, which is kind of annoying.

00:55 If we slow this down, it'll be even more obvious that we've got a cascade going on here where first we have to load that, and then we're loading the image. So that waterfall, not awesome. We'd love to get rid of that cascading waterfall effect there.

01:11 But as part of the design of suspense, this is actually a pretty easy mistake to fall into. So let me explain what that is and how we can optimize out of it. Before I get into that, I'll just mention that this is why there are frameworks

01:29 that are built on top of React and suspense features so that they can kind of do this work for you. Remix specifically is very good at parallelizing things that can be parallelized, and that is something that you probably want to lean on a framework for anyway.

01:46 But let's look at what those frameworks are doing to optimize things a little bit and things that we'll need to do if we use any of these APIs directly. So here we've got profile details. We have use favorites count and get friends. So as this gets rendered, this is going to trigger suspense,

02:05 and we're going to wait, wait, wait, wait. Friends count is done, and now we're going to re-render again, and now we're going to go to get friends. And now, okay, wait, wait, wait, wait, wait. So that is a waterfall effect. If things don't depend on each other, they should run at the same time. And so you could refactor your code like this.

02:20 And so now they both get triggered, and then we don't actually suspend until we call use, and so we will suspend on this one, and we're waiting for that. But while that's happening, we already called get friends, and so that one's also happening. So that's fine. I don't love it, but it's fine.

02:38 But I wish it was this simple. Often it's not. Sometimes you've got things separated by components. So we've got the profile page, and we're getting the user avatar. We're waiting, waiting, waiting before we even get to rendering the profile details with its optimizations.

02:54 And then we also have the profile posts, and who knows what that thing's doing. So we could just take everything and hoist it up, just do all of our promise creating at the top of our profile page component and then pass those promises down. I mean, you can do that.

03:12 That is totally a thing you could do. I don't love it personally, but, yeah, you could definitely do that. Another thing that you could do is instead just leave them all where they're at, but then you can preload. So just call it because we have it cached anyway.

03:26 So just call it ahead of time, and then by the time we get to calling use on all of those, then it will work out just fine. And that also works, but that means you have to remember, okay, which one of these things do I need to call? And maybe if we delete this, then we have to delete that.

03:44 And keeping track of that is kind of annoying. So maybe you could make the component have a property that's a function on it that is called load data. So that way you don't have to keep things up to date.

03:58 Those different things can just make their own way in loading the data, and then even we could handle this in this way, too, so we don't have to worry about keeping those things in sync. That would technically work, but I hate this a lot.

04:16 Yeah, don't like that very much. It is what it is. We could also do all of our uses up in the profile page and then use composition. There's another solution that you could use to just have all the data in one place and then compose all the way down, and that would technically work.

04:34 So, again, this is why we use frameworks. React Router or Remix, they're the same thing, but they have really great data loading mechanisms that hook into suspense really nicely and avoid a lot of these problems.

04:52 And so that is what I would generally recommend. You also have server components, and so server components suffer from some of these same issues, and that's a whole other workshop that we'll get into later. So, yeah, use a framework is what my recommendation is. But we're going to implement some of these optimizations anyway just so that you have it in your mind

05:11 and you can play around with it and understand what's going on. The other optimization we're going to do really quick is a cache control so that even if you refresh the page and come back to one of these, the data and everything is already cached, so it's really fast still. The cache that we have right now is just in memory for the promises.

05:30 And so, like, when you refresh the page, that thing's gone. So we're going to do a little bit of server work on this one. Should be a little fun. And when you're all done, the experience should be a bit faster. So even on a slow 3G network connection, it should be faster. Okay, I think that's enough. Let's get into it.