This specification describes a browser API to enable developers to signal the priorities of the resources they need to download.
This is an unofficial proposal.
This section is non-normative.
The browser's resource loading process is a complex one. Browsers discover needed resources and download them according to their heuristic priority. Browsers may also use this heuristic resource priority to delay sending certain requests in order to avoid bandwidth contention of these resources with more critical ones.
Currently web developers have very little control over the heuristic importance of loaded resources, other than speeding
up their discovery using
<link rel=preload>. Browsers make many assumptions on the importance of resources based on the resource's type (AKA its request destination),
and its location in the containing document.
This document will detail use cases and a markup sketch that will provide developers with the control to indicate a resource's relative importance to the browser, and enable the browser to act on those indications to modify the time it sends out the request and its HTTP/2 dependency/weight so that important resources are fetched and used earlier, in order to improve the user's experience.
FastCorp Inc. have a web app with a mix of async scripts that are critical and non-critical to the initial experience. They want to signify the importance of these resources to the browser. They can accomplish this by annotating these requests with the `importance` attribute:
The browser will attempt to fetch main.js with a high priority and the other scripts with a lower priority.
<script src="main.js" async importance="high"></script> <script src="non-critical-1.js" async importance="low"></script> <script src="non-critical-2.js" async importance="low"></script>
Third party resources (e.g scripts from ads) are often loaded with medium/high priority, but developers may wish to load them all at low priority. Similarly, developers may wish to load all first-party resources that are critical with a high priority.
FastCorp Inc. have a page that includes a number of third party resources which are not-critical to first paint. They would like to signify to the browser that the importance of these resources is low so that requests for them don't contend with network requests for more important resources. They can accomplish this by annotating these requests with an `importance` of `low`:
<script src="https://foo.com/non-critical.js" importance="low"></script> <script src="https://foo.com/ads.js" importance="low"></script> <link rel="stylesheet" href="https://foo.com/footer.css" importance="low">
Markup images are typically loaded with low priority, but may be critical to the user experience, so for certain images, the developer may want to indicate that their importance only falls short of the page's render blocking resources. A prominent example of that is the page's image in an image sharing site, where the image is the main content users are looking for. Another example is a single-page-app where route fetches must run at highest priority.
FastCorp Inc. have an image sharing section of their site where individual images have their own dedicated pages. Although there are several resources loaded for each of these pages, the image is the main content users are interested in. Related images are the next most important. They want to indicate this importance to the browser:
<main> <img src="family.jpg" importance="high"> </main> <section id="related"> <img src="graduation.jpg" importance="high"> <img src="wedding.jpg" importance="high"> </section> <script src="social-buttons.js" importance="low"></script> <script src="analytics.js" importance="low"></script>
Markup-based signals should be added in a way such that non-supporting browsers will simply ignore them and load all resources, potentially not with the intended priority and dependency. Script-based signaling APIs should be created in a way that non-supporting browsers simply ignore the signals.
We propose to address the above use-cases using the following concepts:
importancewhich informs the browser of the importance a developer intends for a resource to have.
high- The developer considers the resource as being high priority.
low- The developer considers the resource as being low priority.
auto- The developer does not indicate a preference. This also serves as the default value if the attribute is not specified.
importanceattribute as a hint of the preferred priority with which the resource should be fetched.
With this attribute, the browser should make an effort to respect the developer's preference for the importance of a resource when fetching it. Note that this is intentionally weak language, allowing for a browser to apply its own preferences for resource priority or heuristics if deemed important.
This is how we conceptually think about different resource types under the hood in browsers today. It may translate well to user-space where different types of content share similar properties.
This section outlines the different use-cases this effort sets to address. It is worth noting that priority in these examples should not limit itself to network priority (i.e. request time and HTTP/2 dependencies and weights), but also to processing priority, as the browser can use the same signals in order to avoid processing of low priority resource in favor of higher priority ones.
The browser assigns priorities and certain dependencies to downloaded resources and uses them to determine:
The browser uses various heuristics in order to do the above, which are based on the type of resource, its location in the document, and more.
Occasionally, web developers are in a better position to know which resources are more impactful than others on their users' loading experience, and need a way to communicate that to the browser.
<link rel=preload> in order to get the browser to early-discover certain resources, especially in its header form, means that the browser
may discover these resources before other, more critical resources and send their request to the server first. That can
result in loading regressions as the server may start sending those non-critical resources before other, more critical
ones, which may fill up the TCP socket sending queues. While better transport protocols (e.g. QUIC) may address that at
a lower layer for the single origin case, developers should be able to signal to the browser that a certain resource is
not critical, and therefore should be queued until such resources are discovered. Such marking as "non-critical" should
be orthogonal to the signaling of the resource's "importance" (e.g. this could be applied to high priority resources that
shouldn't contend with rendering-critical resources as well as low priority ones).
When loading resources from multiple origins, setting HTTP/2 dependencies and weights do very little to avoid bandwidth contention between the origins, as each origin tries to send down its most critical resource without knowing of more critical resources in other origins. Signaling resource importance to the browser can enable it to defer sending of non-critical third party requests while critical resources are still being downloaded.
Developers need a way to provide the above signals for resources that are loaded through markup (or through markup-equivalent
HTTP headers, e.g.
fetch() API. That would enable them both to upgrade and downgrade those resource's "importance".
When developers load a third party iframe, they may wish to make sure that it does not contend on bandwidth and/or CPU with the more important first party content of the page. Alternatively, they may wish to signal the browser that a certain third party iframe is as important as the main page content and should be given CPU and bandwidth resources accordingly.
When such a signal is applied to an iframe, it should be equally applied to all the subresources that the iframe loads.
The importance attribute accepts three possible values: low, high and auto.