This specification describes a browser API enabling developers to signal the priority of each resource they need to download. It introduces the importance attribute that may be used with elements such as img, link, script and iframe.

This is an unofficial proposal.

Dependencies

The term preload is defined in [ PRELOAD ].

The term prefetch is defined in [ RESOURCE-HINTS ].

The term Fetch API is defined in [ FETCH ].

The term destination is defined in [ FETCH ].

The term enumerated attribute is defined in [ HTML ].

The term invalid value default is defined in [ HTML ].

The term missing value default is defined in [ HTML ].

Introduction

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 might 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 mostly determine a request's priority based on the request's destination, and location in the containing document if applicable.

This document details use cases and a markup that will provide developers with the control to indicate a resource's relative importance to the browser, enabling the browser to act on those indications to influence the request's overall priority in ways described in the Effects of Priority Hints section.

Solution

The importance enumerated attribute may be used with resource-requesting elements including link, img, script and iframe. This keyword hints to the browser the relative fetch priority a developer intends for a resource to have.

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. See the below section for more information.

Priority Hints complement existing browser loading primitives such as preload. Preload is a mandatory fetch for a resource that is necessary for the current navigation. Priority Hints can hint that a resource's priority should be lower or higher than its default, and can also be used to provide more granular prioritization to preloads.

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.

Effects of Priority Hints

Since the user agents' resource loading pipeline is largely unspecified, this document doesn't describe a specific mapping between Priority Hints and request prioritization. However, it does describe ways in which implementations are encouraged to influence a request's overall fetch priority given a Priority Hint.

HTTP/2 Relative Stream Priority

Implementations are encouraged to use Priority Hints to influence the HTTP/2 stream priority assigned to a given request. It is not the intention of the different importance states to directly map to existing browser priority values, but instead act as a relative influencer among requests of a similar type.

If requests for image destinations in a particular implementation are typically assigned a stream weight of 60, a request for an image with importance="low" might be assigned a stream weight less than 60. In other words, importance="low" on an image might lead to an entirely different resolved HTTP/2 stream priority than importance="low" on something like a script, or an iframe.

Queueing

A user agent might choose to queue up certain low priority requests until higher priority requests are sent out or finished in order to reduce bandwidth contention. Implementations are encouraged to use Priority Hints to determine whether a given request is a candidate for such queueing so that more important resources are fetched and used earlier, in order to improve the user's experience.

Examples

Lower fetch priority when browser defaults are insufficient

Browsers make a best-effort to assign a reasonable fetch priority to images so those in-viewport appear as soon as possible. In many cases, this will not cause issues, however, what if some above-the-fold imagery is not as critical as others? Priority Hints can assist here.

FastCorp Inc. have a carousel of images at the top of a page with the first image visible and the remaining images images off screen. The markup of this carousel may look as follows:

<ul class="carousel">

<!-- The first image is visible -->
<img src="img/carousel-1.jpg">
<!-- The other carousel images are not -->
<img src="img/carousel-2.jpg">
<img src="img/carousel-3.jpg">
<img src="img/carousel-4.jpg">
</ul>

Browser heuristics may cause all four images to be fetched with a high priprity, despite three of them not initially being visible. This may cause these fetches to delay the first image from completing fetching or contend with fetches for other in-viewport resources.

A developer could use rel=preload to preload the first image in the carousel, however doing so may not provide the outcome one expects: rel=preload will effectively prioritize that image above everything else, and if that image is large, it may block rendering as even stylesheets may end up waiting for that image to complete downloading. Priority Hints may help here.

<ul class="carousel">

<!-- The first image is visible -->
<img src="img/carousel-1.jpg" importance="high">
<!-- The other carousel images are not -->
<img src="img/carousel-2.jpg" importance="low">
<img src="img/carousel-3.jpg" importance="low">
<img src="img/carousel-4.jpg" importance="low">
</ul>

When we assign the off-screen images low importance, this will create less contention between the remaining high priority images and other high priority resources.

Speed up resource loads without incurring the cost of rel=preload

Some UAs fetch scripts with medium priority. Using `importance=high` on them has the benefit of speeding this up without incurring the cost of `rel=preload` contending with higher-up-the-page render blocking resources:

FastCorp Inc. have a web app with a mix of resources that are critical and non-critical to the initial experience. They want to signify the importance of their primary script without using rel=preload, which would contend with their render blocking stylesheet:

<link rel="stylesheet" href="https://foo.com/main.css">
<script src="main.js" importance="high"></script>
  

In the below example, using rel=preload, async styles may normally be loaded at the highest priority. Priority Hints can help us here to ensure the loading of the stylesheet doesn't content with any render-blocking or more critical resources.

<link rel="preload" as="script" href="critical-script.js">

<link rel="preload" as="style" href="theme.css" importance="low" onload="this.rel=stylesheet">
Reduce network contention from third-party resources

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>
      
Reduce network contention from non-critical Fetch API requests

Priority Hints can be used to lower the priority of non-critical Fetch API requests to avoid them contending with more important ones.

A news site making a critical Fetch API request for article content might end up contending with requests for less important resources like related content.

<script>

// Critical Fetch request for article content
fetch('/api/articles.json').then(/*...*/)

// Request for related content contending with the above request
fetch('/api/related.json').then(/*...*/)
</script>

By using the importance attribute on the second Fetch request, we can hint that the priority of that request is low, reducing the chances of it contending with the Fetch request for article content. We can also explicitly state the priority of the first request is high so that browsers where Fetch requests do not already have a high priority know that it is important to the page.

<script>

// Critical Fetch request for article content
fetch('/api/articles.json', { importance: 'high' }).then(/*...*/)

// Request for related content now reduced in priority
// reducing the opportunity for contention
fetch('/api/related.json', { importance: 'low' }).then(/*...*/)
</script>

This might be more pronounced on HTTP 1.1 with the impact being more visible with HTTP/2 multiplexing if a large number of Fetch requests are being made and are contending with one another.

The importance hint may be specified in the document markup, MAY be provided via JavaScript, MAY be provided via the HTTP header, and MAY be dynamically added to the document.

Link: </app/style.css>; importance=high
Link: </app/script.js>; importance=low

As above examples illustrate, importance can be specified via declarative markup, Link HTTP header ([ RFC5988 ]), or scheduled via JavaScript.

Adoption path

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.

Out of scope

Use Cases

This section outlines the different use-cases Priority Hints sets out 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.

Communicate resource importance to the browser

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.

Signal a resource as non-critical

Using <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).

Avoid bandwidth contention in multiple origin scenarios

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.

Provide priority signals for markup-based resources

Developers need a way to provide the above signals for resources that are loaded through markup (or through markup-equivalent HTTP headers, e.g. Link:)

Provide priority signals for dynamically loaded resources

Developers need a way to provide the above signals for resources that are fetched through JavaScript, e.g., using the fetch() API. That would enable them both to upgrade and downgrade those resource's "importance".

Provide the ability to re-prioritize a resource in-flight

Downgrade priority of an iframe and its subresources

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 to 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.

Safe usage

If the importance keyword is used as an optimization to initiate earlier fetch then no additional feature detection checks are necessary: browsers that support importance may initiate earlier fetch, and those that do not will ignore it and fetch the resource as previously. Otherwise, if the application intends to rely on importance to fetch the resource, then it can execute a feature detection check to verify that it is supported.

Applying importance to the resources in a page should never degrade performance. This should hold true for both browsers that support Priority Hints as well as browsers that do not. UAs are free to apply other heuristics in addition to Priority Hints to decide on how they load content.

With in-viewport images, a browser may automatically detect if the image is important and boost priority if it gets to layout early enough. However, all browsers would benefit from knowing which images an author wants to load "earlier" and which are safe to load "later", regardless of how they use this information.

This same logic applies for scripts. Browsers may have different heuristics that work differently across browsers for scripts (e.g with async, defer) but a site could fix any misguesses across the board by being explicit using Priority Hints.

References

Normative references

[PRELOAD]
Preload . Ilya Grigorik, Yoav Weiss. W3C. 9 January 2018. W3C Editor's Draft. URL: https://w3c.github.io/preload/
[RESOURCE-HINTS]
Resource Hints . Ilya Grigorik. W3C. 4 May 2017. W3C Working Draft. URL: https://www.w3.org/TR/resource-hints/
[RFC5988]
Web Linking . M. Nottingham. IETF. October 2010. Proposed Standard. URL: https://tools.ietf.org/html/rfc5988
[FETCH]
Fetch Standard . Anne van Kesteren. WHATWG. Living Standard. URL: https://fetch.spec.whatwg.org/
[HTML]
HTML Standard . Domenic Denicola. WHATWG. Living Standard. URL: https://html.spec.whatwg.org/multipage/