Check out a free preview of the full Web App Performance course
The "Preloading" Lesson is part of the full, Web App Performance course featured in this preview video. Here's what you'd learn in this lesson:
Max preloads the primary image on the page to improve the First Contentful Paint metric. Preloading an asset with a link element and rel="preload" will speed up the discovery process and potentially have the asset in the browser cache by the time the application requests it.
Transcript from the "Preloading" Lesson
[00:00:00]
>> LPC, we mentioned that LCP, Largest contentful paint, is the most important metric for our website, right? So it's the largest part of content that the user's brain will parse, so we need to hack that as much as possible. One thing that we can do is preload.
[00:00:18]
What is this? It will help the browser discover resources that are obscure in the document. Let's try to understand what that is first. Going back to our solution, that remember, you can try on your own device, let's see our content here. Let me get out of this, Frontend Museum.
[00:00:44]
I think that image is our largest contentful paint, okay? So if you look at the image, the image is gallery/ancient-greece.png, okay, that's the name of the file. Okay, when we see here, it's not in the HTML. So we know it's important. Actually, it's the most important part for performance.
[00:01:07]
We want that image as soon as possible, right? We all agree on that, right? So if we go to the Network tab, I'm going to move it. Where is that jpg file here? Let's see. That's a script, that's a logo, that's a gradient, that's a font, the JSON, ancient-greece, here it is.
[00:01:29]
So when we look at the diagram, we wasted all this time to actually download the file earlier. And if I see the details of that, we can see that it was queued at 516 second. What is that? That is at that moment it was discovered. When it's queued is when it's discover.
[00:01:58]
So for five seconds, the browser didn't know about that PNG file. That by the way, shouldn't be a PNG, but that's for another slide. So what's going on? So we need to analyze what's going on. Why is that the browser is not downloading that PNG file faster? Well, the problem is that on how this website is being created, that there are a lot of websites out there, like there is a script file that we can see.
[00:02:27]
The script file, it's registering an event on the load event, okay? We already mentioned that. Is it a good idea? No, the load event will happen after all the images and everything is downloaded. So we can start helping this. We can change onload for onDomContentLoaded or use addEventListener.
[00:02:52]
It's DOMContentLoader. So I'm going to call load on DOMContentLoaded. This will save a couple of milliseconds, if not seconds, to start executing this code. Then this code is downloading a JSON file. And based on that JSON file, it's rendering articles on the screen. That's why the image is being discovered late.
[00:03:18]
So the browser needs to execute the JavaScript. So it was waiting for the load, executing the JavaScript, going and fetching the JSON, then parsing the JSON, then looping through the objects that we have there, and creating HTML. At one point, the browser says, there is an image I need to go and find.
[00:03:40]
We lost not five seconds, but probably four, and we could download that PNG file earlier. So we can, of course, change this. So we have a big problem here. The big problem is that this was a bad idea from the first time, okay? So rendering content on the screen based on JavaScript that needs to download a JSON file is a bad idea from the scratch.
[00:04:07]
But let's say that for now we cannot change that, what else we can do? We can use preload. So we can help the discovery of that file with preload. Preload is a link element that we can set typically in the head of our HTML. And in this case, we are going to help that queue of discovered elements.
[00:04:34]
We are going to say, hey, browser, we will need that PNG file. You don't know yet that we will need that, but believe me, I'm the author. I know that you will need that later. So for that, then we go to the HTML and add that link. It's link rel="preload".
[00:04:56]
The name is going to be images/, no images, no, I'm sorry gallery/. It was ancient-greece, and it's mandatory to set as. So I'm going to download this as an image, as a style sheet, as a script. So there is a list in the spec of values for that 'as'.
[00:05:20]
So in this case, we are moving within the timeline within our waterfall chart, the discovery of that element. We will still have the problem that the browser will not know what to do with it for a while before executing the JavaScript. But at least when that moment is there, the image is there waiting for the browser, so it will be rendered faster.
[00:05:46]
Does it make sense?
>> Sorry, so that link with the preload, that line there when actually display the image.
>> No.
>> It try to prepares it for when it's in. So when is it actually being asked to be rendered? It's within that script?
>> We didn't change that, we didn't change that part.
[00:06:04]
In this case, it's the script. The only thing that we change, we change the event. So now instead of being the load event, we improve that a little bit on DOMContentLoader. And within this event is fetching that data.JSON. And for each element that we have here, we are creating this little HTML that we're injecting, and that HTML is gonna have an image.
[00:06:25]
>> Yeah, and so at that line there in that loop there-
>> Here, and that line 13, actually, not even in the line 13. When we release the thread of that event listener, the browser will say, okay, let's see what has just passed. It will say, we have more HTML to render.
[00:06:44]
It will parse that new HTML, it will update the DOM, and it will realize that there is a new image to render, and it will fire the queue, not this one. I think, yeah, this one. It will need a resource. It will check the cache. It's in the cache.
[00:07:04]
So actually, it's a cache hit and it's not expired. So you will use the file from the cache. It works like that, that's the idea. So when you need it, when the browser needs that file, it's there. I'm in the final version. No, I'm applying small updates, okay, to these code to make it even better, okay?
[00:07:27]
I'm not saying that it's fine, but it's getting better on each iteration. So how do I know? And now it's better, look at the image now. Let's go like this ancient-greece now is being downloaded in parallel with the CSS immediately. I'm not saying it's being rendered there after downloading the file, because I'm not saying that because it's not happening.
[00:07:51]
But at least it's being downloaded as soon as possible, and then when the JavaScript is executed. This is the JavaScript file. And then the data.json file is here. So after this is parsed at that point, it realized, yeah, the image, but the image was already downloaded. So we use data preload, sorry, we use link rel="preload" to help that discovery process.
[00:08:22]
And we typically use that for elements that are hidden or obscure in the HTML. So we don't typically do that with logo.png. There is no need for that, because logo.png is already in the HTML defined. So the discovery will happen anyway pretty soon.
>> What would happen if you just put that on every single?
[00:08:43]
>> Well, if you add that on every single element, what happens is that when everything is important, nothing is important. So it's like not doing it, actually. The advantage of using these APIs is that now you have control to help the browser prioritize what you need to make it better that by default, the browser doesn't know exactly what will happen with that website with that rendering process.
[00:09:14]
But we know because we are the authors, so we know what we are trying to achieve here, and then based with that we wanna improve LCP. And we know that that image is the LCP, then we apply that. So this is one example for preload. In our work code, what other example do we have for preload?
[00:09:34]
How fonts work? This is a CSS file, okay? So this link is not downloading the font. This link is downloading the CSS file that is pointing to a font. Does it make sense? If the font is important for LCP, I'm not saying it's the case for every case, we should check which of these fonts are the ones I need.
[00:10:00]
How do I check that? Well, maybe I can go to the network layer and see which font file is being downloaded. It's this one. So if I believe that font is mandatory for the LCP, don't do this for every font, only for the one that you know it will improve or it may improve your web vitals.
[00:10:26]
You can go copy the URL, and add the rel ="preload", For the fonts file itself. So rel="preload" href=, that long list, long URL, as"font">. So in this case, that URL, the actual, it's a woff file. That woff file was obscure for the HTML, the HTML didn't know about that.
[00:11:02]
The HTML need to first download the CSS, parse that CSS to actually know that woff file. Well, we can preload it, that's another use case. But again, don't add preload on everything or don't add preload with elements that are already visible in the HTML. So if you see the reference in the HTML, you don't need to preload, because it will be in the queue anyway.
[00:11:29]
Preload is being used to actually help the discovery. By the way, if you're wondering why, if you try this Frontend Museum website, every time you reload, it's different, right, the performance sometimes it's better, sometimes it's worse. It seems a little bit inconsistent, right? Why is that? And I'm sure if you were curious enough to go and see what's going on, the server is actually making a pause.
[00:11:57]
It's a middleware in express.js, that is making a random delay. Let's say a fake delay on every request from 100 to 1,600 milliseconds. So every request, every image, every CSS will have a delay. It's like the server is, or the latency. I'm faking this so we can see better in action how small changes in the front end can lead to much better web vitals.
[00:12:27]
So instead of adding it in the HTML, you can even went a little bit lower in the timeline and add that as an HTTP header in the response. So you a browser, you're asking me for the HTML and I'm responding, I'm saying, hey, go and download that CSS.
[00:12:52]
Here, you have the HTML. So then your browser will know that CSS or that woff file will be needed even before starting rendering the HTML. Does it make sense? So then with the headers, the browser will know that there is a need to preload some other resources.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops