When you open your browser’s network tab, you’ll see a ton of activity. Resources are being downloaded, information is being submitted, events are being logged, and so on.
With so much activity, effectively managing the prioritization of this traffic becomes critical. Bandwidth contention is real, and when all requests fire at the same time, some HTTP requests are not as high priority as others. For example, if you had to choose, you might prefer someone’s payment request to complete successfully rather than just an analysis request indicating that they attempted it. And having your main image appear as quickly as possible is undoubtedly more important than rendering your logo at the bottom of the page.
Fortunately, browsers have a growing number of tools to help prioritize all this web activity. These “priority hints” help browsers make fewer assumptions and clearer decisions about which requests should be prioritized when resources are limited.
This is a useful set of tools that, when used well, can have a substantial impact on page performance, including those increasingly important core web metrics. Let’s explore some of them, and some of the scenarios in which they are most helpful.
This is a useful set of tools that, when used well, can have a substantial impact on page performance, including those increasingly important core web metrics. Let’s explore some of them, and some of the scenarios in which they are most helpful.
Resources loaded first
Modern browsers have a well-supported way of telling the browser what resources the current page will ultimately require: . When it is placed in the
of a document, the browser is instructed to download it as quickly as possible with “high” priority.
To be fair, preload scanners in browsers are already pretty good at this. Therefore, preloading usually works best with resources that are discovered later – anything that is not loaded directly by your HTML, such as a background image loaded via an inline style attribute. But it also works for anything else that might not be prioritized by the browser as much as you’d like.
For example: By default, Chrome loads fonts with very high priority, but if someone has a slow network connection, it will use fallback fonts and lower that priority.
Consider a font loaded only via the CSS @font-face rule:
@font-face { font-family: "Inter Variable"; src: url("./font.woff2") format("woff2"); }
When loading, this font received the lowest download priority due to a slow network connection, even though it is very important to the visual experience of the page.
But we can override the browser’s decision by preloading the resource:
<head> <!-- Other stuff... --> <link rel="preload" href="/font.woff2" as="font"> </head>
Now it’s even more popular:
You can use fetchpriority
directly on the link tag to explicitly indicate relative priority, which is useful when preloading multiple resources at the same time.
Here’s a hypothetical scenario where you want to preload two fonts, but want to prioritize one over the other:
<link rel="preload" href="./font-1.woff2" as="font" fetchpriority="low" /> <link rel="preload" href="./font-2.woff2" as="font" fetchpriority="high" />
The results of network activity reflect these indications.
When to use
Typically, preloading is used when resources are not loaded directly by HTML, but are critical to the experience of the page (such as fonts, CSS background images, etc.). When fetching multiple resources of the same type and you know exactly which one is most important, add the fetchpriority
attribute.
Prioritize fetch() requests
In my opinion, the Fetch API is one of the best tools for the modern web. It has some nice features compared to XMLHttpRequest
, such as the ability to signal priority on outgoing requests.
The most obvious use case that comes to mind is: Analysis requests. When bandwidth is limited and there are multiple requests in progress, the browser determines its own priorities. But we as engineers should know that general analysis requests should take precedence over other requests that are more critical to the purpose of the page. Modern fetch()
makes this easy.
Here’s a simple setup where two requests are enqueued at almost the same time:
fetch("http://localhost:8000/pay", { method: "POST", body: paymentBody, }); fetch("http://localhost:8000/log", { method: "POST", body: loggingBody, });
By default, the browser automatically treats them both as “high” priority:
Now, we need to explicitly tell the browser the priority of each request:
fetch("http://localhost:8000/pay", { method: "POST", body: paymentBody, + priority: "high" }); fetch("http://localhost:8000/log", { method: "POST", body: loggingBody, + priority: "low" });
This time, the priorities are different:
A possible concern is that “low” priority requests may be lost – if the user leaves the page prematurely, the request may be canceled. This is a real problem. Depending on several factors, closing a tab or moving to the next page may cause an important but relatively low-priority request to be aborted.
Fortunately, fetch()
also accepts a keepalive
option. When set to true
, the browser will complete the request even if the page terminates.
When to use
Indicate the priority of fetch()
when you know that multiple requests are executing concurrently, and you know exactly which one is most important (or which one can be safely demoted).
Prioritize
requests
If we don’t do anything special, the browser will try to determine the most important image on the page. To illustrate this, I loaded the following images with a large distance between them so that only one will be displayed at the “header” of the page.
<img src="./cat-1.jpeg" /> <div style="height: 5000px"></div> <img src="./cat-2.jpeg" /> <div style="height: 5000px"></div> <img src="./cat-3.jpeg" />
The browser figured out which one was most important, but it took a second. All three are “low” priority when downloading begins. But soon, the one at the head of the page switched to “high” priority.
Things become more predictable when I add the fetchpriority
attribute to the first image:
<img src="./cat-1.jpeg" fetchpriority="high" />
Thereafter, cat-1.jpeg
is loaded with highest priority from the beginning. While initially confusing, it makes sense. The browser is very good at determining the criticality of resources, but it benefits from explicit instructions. If you know an image is important, make it clear.
By the way, this feature works great with local image lazy loading, which is a very supported feature now.
<img src="./cat-1.jpeg" fetchpriority="high"/> <div style="height: 5000px"></div> <img src="./cat-2.jpeg" loading="lazy" /> <div style="height: 5000px"></div> <img src="./cat-3.jpeg" loading="lazy" />
With this, the browser knows how to load the image and only loads it when appropriate. In my case it wouldn’t even start requesting the off-screen image on initial load. Instead, it waits until they are closer to the viewport.
When to use
Use explicit fetchpriority
for images when you know they are important to the page experience. The main image is a great place to start, and it can even impact a page’s core web metrics – specifically LCP
(maximum content draw).
Prioritize
tags
Any normal on the page with a
src
attribute will get high priority when fetched, but there is a trade-off: before it loads and executes, it will prevent the rest of the page from being parsed. For this reason, the async
attribute is useful. It requests the script in the background with low priority and executes it as soon as it is ready. Knowing this, the following setup behavior is predictable:
<script src="/script-async.js" async onload="console.log('async')"></script> <script src="/script-sync.js" onload="console.log('sync')"></script> <script>console.log("inline");</script>
Asynchronous scripts are lowered in priority:
The console confirms that during async
script loading, subsequent scripts are allowed to be parsed and executed.
Non-blocking, but high-priority script
Most of the time, this behavior is fine. But sometimes, you may want a script to both load with "high" priority and also load asynchronously.
One possible scenario is to install a small SPA
in the hero section of the landing page. In order to preserve the core network metrics of the page, specifically LCP
and FID
(first input delay, quickly replaced by the next drawn interaction), you need to give this a high priority Script (after all, it is responsible for building and powering your application). But at the same time, you don't want it to prevent the rest of the page from being parsed.
So, we give it a fetchpriority
:
<script src="/script-async.js" async onload="console.log('async')" fetchpriority="high"></script> <script src="/script-sync.js" onload="console.log('sync')"></script> <script>console.log("inline");</script>
Now it downloads with increased priority while still not blocking other parts of the page:
The console verified this. With a higher priority, asynchronous scripts load faster. In this case, it's even faster than synchronous and inline.
While I'm not specifically playing around with it here, yes, fetchpriority
also works with deferred scripts.
When to use
Put fetchpriority
on your script when you know the priority of your script ahead of time and suspect that the browser may not have enough information to decide for itself. As I mentioned, prioritizing scripts that you want to load in a non-blocking, asynchronous manner is especially helpful.
Intentional use
It's easy to get too enthusiastic about a tool like this, leading to overuse. So, be careful - there may be a price to pay for doing so. As the saying goes: "Emphasis on everything = emphasis on nothing." In fact, overuse may actually make it harder for the browser to manage network contention, hurting the performance of the page.
MDN even goes so far as to point out in their priority tips documentation:
Only use it in special cases where the browser may not be able to automatically infer the best way to load the resource. Overuse may result in performance degradation.
So, don’t feel obligated to use these tools just because they exist. Use with caution.
Review: When to prompt
There’s a lot to cover here, so let’s quickly review when you might choose to use priority prompts. None of these are exhaustive. Just some good starts.
-
Prompt for preloaded resources when you want the browser to be aware of multiple later-discovered resources, some of which are more critical to the page than others.
-
Prompt for
fetch()
requests that you know are a critical part of the user experience, or can be safely demoted to make way for more important requests. -
Prompt for above-the-fold images that you want to load and display as quickly as possible.
-
Prompt scripts that are critical to the functionality of the page, but you don't want to prevent other parts of the page (including other resources) from being parsed and downloaded.
Let the browser guess less
Browsers are very good at figuring out how and when to download the stuff that makes our pages run. But it's not always that good. It has no idea why a page exists or the intent behind its various parts. So occasionally, it could use a little extra help.
That's why these priority hints exist: to make instructions clear and give the browser less chance of making the wrong decision. The next time you study your own application's network activity, remember them and, when they make sense, use them to help make your page performance smarter.
Welcome to long press the picture to add dishwasher as a friend and share Vue React Ts regularly.
at last:
vue2 and vue3 skills collection
VueUse source code interpretation