Introducing Deferred Props0:00
All right, next up, I want to show you deferred props in Inertia 2. All right, let's break it down. What does that mean? Well, defer means what? To postpone or to put off, right? So, if we combine that with props, we are putting off or postponing the loading of props. And I'll show you why you might want to do that. All right, so here's my demo. On my dashboard, I have a link to one thing, courses. And this lists all of our fictional courses for this site. And there's a bunch of them. But now notice when we get to the bottom, we see another section that lists all topics on the site.
And there's a bunch of them. But now notice when we get to the bottom, we see another section that lists all topics on the site. And yeah, these are just ways to filter the content or the courses. All right, so if we have a look in my editor, we have two routes. One for dashboard, and yeah, that's just this section right here. Very simple. And then the next one is /courses where, well, we have two pieces of data, right? One that fetches all courses from the database. Maybe, maybe not wise there, but it's great for a demo. And then another one for topics.
Maybe, maybe not wise there, but it's great for a demo. And then another one for topics. All right, so if we click through here, very quickly, we accept them as props. And yeah, as you'd expect, we have one View component for a CourseCard and another View component for a TopicCard. It's just a wrapper for a bit of HTML. Loop over the courses and display each one. And then loop over the topics and display each one. All right, so this is great. No problem whatsoever.
Simulating Slow Queries1:23
All right, so this is great. No problem whatsoever. However, one thing that you'll often run into in real life is, well, sometimes these things take a bit of time to load, right? Maybe it takes even a second or so. And it's a shame to make the user wait for whatever logic you have to complete before they can begin browsing the site. But currently, that's what they'd have to do. So here's how I'm going to simulate that. For courses, let's convert this to a traditional closure.
So here's how I'm going to simulate that. For courses, let's convert this to a traditional closure. And I'm going to represent some kind of heavy database query just by sleeping for a little bit. So we'll say sleep for two seconds. And then I'm going to do the same thing for topics, but not quite yet. So back on my dashboard, I will open up the Network tab, and let's give it a shot. I click on Courses, click, and we count. One, two, and yeah, now it loads in.
I click on Courses, click, and we count. One, two, and yeah, now it loads in. And we can see right here, yeah, it took exactly two seconds to load. So that's a bit of a shame, right? Now we can see that the User has to wait for all of the logic here to complete before they can continue interacting with our site. So if you think about it, wouldn't it be cool if there was a way to just instantly load that courses page, and then as part of a separate request,
if there was a way to just instantly load that courses page, and then as part of a separate request, we could pull in the courses and display them only when they're ready. But in that time, the user can start scrolling and interacting with the page. All right. So maybe we can do that, but before we do, yeah, let's just expand this a little more. I'm going to do the exact same thing for topics, and we'll say just like courses,
I'm going to do the exact same thing for topics, and we'll say just like courses, we're going to simulate some kind of heavy logic or query by sleeping for a couple seconds. So now I want you to ask yourself, when we load the courses page, will it take two seconds to load or four seconds to load? Let's have a look. All right, let's give it a shot. Bring back the Network tab.
All right, let's give it a shot. Bring back the Network tab. I click on it. One, two, three, four. It took four seconds to load, didn't it? Yep, four seconds and four milliseconds. All right, so that's a shame, right? It makes sense if you think about it. We hit this route, and we load this data, and we have to wait a couple seconds,
We hit this route, and we load this data, and we have to wait a couple seconds, and then we continue on, and we load this data, and we have to wait a couple seconds. So now, effectively, before the User can interact with our site, they have to wait exactly four seconds, one, two, three, four, before they can continue on their way, which is just monstrous. We can't allow that.
Deferring Props Backend3:46
which is just monstrous. We can't allow that. So let's figure out what we might do. I'm going to switch back. All right, so here's what we'll do. For Courses and Topics, I'm going to wrap both of them within a call to InertiaDefer, and, of course, this is new in Inertia 2. All right, and again, yeah, I just find that this word defer scares people,
All right, and again, yeah, I just find that this word defer scares people, but it shouldn't. You already know what it means, to put off, right? So all I'm saying is, all right, for this piece of data, Courses, I actually want Inertia to put off the loading of this data, or, in other words, fetch this data as part of a separate request, and we're going to do the exact same thing for Topics.
fetch this data as part of a separate request, and we're going to do the exact same thing for Topics. So effectively, it's going to kind of skip over Courses and Topics for the initial load, and then it's going to make a second request to pull them in. Let's have a look in the browser. Let's come back to Dashboard. There we go. Pull up the Network tab, and let's go. We click on it, and notice, yep, we get two requests.
Pull up the Network tab, and let's go. We click on it, and notice, yep, we get two requests. The first one loads immediately, and that's where I see the Courses page, and then the second one pulls in the extra data. So yeah, check this out. The first request loads the page, and notice for prompts, it skipped over Courses and Topics because we deferred those.
it skipped over Courses and Topics because we deferred those, and you can see that represented right here. All right, then a second request is made where we do pull in Topics and Courses, and that's why that one still takes four seconds. But the important thing is the user was able to interact with the page almost instantly. And of course, we can expand this later to display loading icons.
Prioritizing Deferred Requests5:14
And of course, we can expand this later to display loading icons. Very cool. But now, all right, this makes sense, but yeah, for that second request, we still have to wait four seconds. So there might be situations where you want to add a priority or you want to tag these in a certain way so that some can be pulled in a little quicker than others. For example, imagine that for whatever reason,
so that some can be pulled in a little quicker than others. For example, imagine that for whatever reason, you have 10 million courses, and it's incredibly unoptimized, and it takes five seconds to load this data, and you're not caching for some reason. It's a hypothetical, and it's a demo. Deal with it. Okay, but now, before the User can even see these topics, they have to wait a full seven seconds,
Okay, but now, before the user can even see these topics, they have to wait a full seven seconds, which isn't ideal. So instead, what we could do is tag these, and for the tagging system, do whatever you want. High priority, low, medium, one, two, three, A, B, C. It doesn't matter. That's the entire point. Choose any convention you want. So maybe this could be long, and this one could be short.
Choose any convention you want. So maybe this could be long, and this one could be short. Maybe this could be high priority, and this one could be low priority. Anything you want. The key here is that when Inertia encounters these, it will split them up into any number of requests. So in this case, we have two deferred props and two different keys. So it's going to make two requests instead of just one.
and two different keys. So it's going to make two requests instead of just one to pull in these deferred props. And if we add another piece of data with a third key, then it would make another request. And, of course, they can share these keys. So maybe if we have another piece of data that loads quickly, it can also be included in the low priority or the high priority tag. So now check this out.
or the high priority tag. So now check this out. Back to the dashboard. Open up the Network tab, and we're going to see three requests, right? Let's give it a shot. Courses. And we have one to fetch the initial page, one to fetch the low priority deferred props, and then another one to fetch the high priority deferred props.
one to fetch the low priority deferred props, and then another one to fetch the high priority deferred props. So if we sort these according to time, the page loads in 20 milliseconds, the topics took two seconds to load, and the courses took five seconds to load. Okay. So now we understand the back end. That's all you really need to know. For the front end,
Deferred Component Fallback UI7:22
That's all you really need to know. For the front end, there's a new deferred view component that we can pull in to make this a little easier. Let me show you. Let's go into courses/index, and at the top, I'm already pulling in courses and topics. But now right down here, yeah, we just wait for courses to show up, and then we iterate over them.
yeah, we just wait for courses to show up, and then we iterate over them. And that's why if I come back, we see nothing at all until the six seconds have completed. But do notice because the topics loaded faster and they were in their own request, we saw those first, which is kind of cool. So already we're seeing some of the benefits here. Okay. So I'm going to wrap this
Okay. So I'm going to wrap this within a new DeferredViewComponent like this, and this is all the data that I want deferred. But we have to tell it what we're actually trying to defer. We can do that via the data tab. So everything in here is contingent or waiting on the courses prop to become available. Okay. But now if we keep it just like this,
Okay. But now if we keep it just like this, I think we're actually going to see a warning in the console. Let's have a look. Come back, refresh, and yeah, I don't see anything. Just a white page. I check the console and it lets me know, hey, the deferred component requires a fallback template. So yeah, it's saying, look, while we are waiting for this data to become available,
So yeah, it's saying, look, while we are waiting for this data to become available, what's the fallback? What does the user see? So let's add that now. Here's our fallback template, and it can be anything you want. It could be simply loading. And if I come back, now while that's fetching the courses,
And if I come back, now while that's fetching the courses, it's waiting five seconds, we see loading. But once it gets pulled in, you'll see that it disappears, right? So I believe I've created a loading spinner SVG that I just found on GitHub. I'm going to reference that. And yeah, now this represents something that you might see more in the wild.
And yeah, now this represents something that you might see more in the wild. So if I come back one more time, we're going to fetch courses. That takes five seconds. We see other data loading in, and when this is done, we can now interact with the courses. All right, let's do the exact same thing for our topics. Let's do it again.
All right, let's do the exact same thing for our topics. Let's do it again. Deferred. I'm going to pull this in right here. For our loading indicator, I'll just copy this. That's fine. And once again, it's not enough to leave it just like this. We have to be explicit. What are we waiting on?
We have to be explicit. What are we waiting on? Well, we are waiting on topics to become available for this section. So I could say topics. Now there might be situations where you want to say, well, for a single deferred component, I actually need both courses and topics to be available. So in that case, just bind it to your prop names, courses and topics.
So in that case, just bind it to your prop names, courses and topics. And now until both of those have been pulled in, we will display a loading indicator. But yeah, in this case, we can stick with just topics. All right, so now if we give it another go, we should see two loading indicators. Topics and courses. Topics loads in, and then the courses load in.
When to Defer Data10:14
Topics and courses. Topics loads in, and then the courses load in. Very cool. All right, so here's my recommendation. Don't just default to wrapping everything in inertia.defer. That didn't make sense. As always, you need a reason to switch over to this. You need some kind of performance bottleneck that you need to get around. Because remember, in real life,
that you need to get around. Because remember, in real life, most queries are optimized and quite performant. And if we're talking about 30 milliseconds here, it just doesn't matter. So maybe what we'd find is, well, topics loads incredibly fast because we only have 12 topics. So I don't need to defer that, and I can return that to an arrow syntax.
So I don't need to defer that, and I can return that to an arrow syntax. However, courses, for whatever reason, we just can't solve this bottleneck, and we do need to defer that. All right, so now we would have a single page request that renders the page and also pulls in the topics. And then we would have a second request that loads in the courses. So if we took that approach,
that loads in the courses. So if we took that approach, now, because topics load so quickly, we don't need to wrap these. We can keep it like this. However, courses do require a bit of time, so we do wrap it. All right, so now, if I click on it, yeah, I instantly can see the topics, but it's taken a couple seconds
yeah, I instantly can see the topics, but it's taken a couple seconds for all of the courses to load in. And that's more intended behavior that you might see in the wild. As always, let me know what you think. And you know what? There's even some other ways that we can tackle bottlenecks like this, and I'll show you how in the next episode.
that we can tackle bottlenecks like this, and I'll show you how in the next episode.
