Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Standardize Priority Hints #7150

Closed
pmeenan opened this issue Oct 4, 2021 · 24 comments
Closed

Standardize Priority Hints #7150

pmeenan opened this issue Oct 4, 2021 · 24 comments
Labels
addition/proposal New features or enhancements topic: fetch

Comments

@pmeenan
Copy link
Contributor

pmeenan commented Oct 4, 2021

This is a re-start of the work that was initially captured in #3670

Priority Hints is an API that lets developers signal to the browser the relative importance of resources, so that the browser might take this into consideration when prioritizing the request. The WICG repository for Priority Hints is here and the explainer spec is here. The explainer spec lays out some good use cases. Prioritization might take the form of modifying a request's HTTP/2 or HTTP/3 priority, delaying when a request is sent out, etc.

Browsers already have an internal implicit mapping for fetch prioritization, usually based on content type and combined with other factors (background tab, preload, prefetch, in-viewport, parser-blocking, sync XHR, etc). The prioritization usually impacts the order in which requests are made and, if the underlying protocol supports multiplexing and prioritization, the protocol-specific prioritization of each stream.

Priority Hints gives a developer a mechanism to indicate to the underlying browser, a hint about the relative priority of a given request, either indirectly through the importance attribute on an HTML element that requires a resource load (img, script, preload, etc) or explicitly as an attribute on a fetch API call. The browser can take the importance hint into account when evaluating priorities to assign to individual resources.

The intent is to provide an additional developer-controlled signal to help with cases where heuristics are not enough to result in optimal loading. There should be no functional changes as the underlying processing model is not altered.

The working group settled on high/low signals (in addition to the default of auto) as a way to give developers some input into the prioritization without exposing the complexity of the different underlying protocol implementations and to continue to allow for browser heuristics. Chrome has documented the current prioritization heuristics here including the changes that Priority Hints apply.

Concrete Use Cases

Boosting Image Priority

By default, Chrome gives images a relatively low priority because they do not block the parser or the DOM Content Loaded event from firing. There are some heuristics to boost the priority of in-viewport to get the visual content loaded sooner but that priority boost can only be applied after the initial layout has been performed and the images within the viewport can be identified.

Priority hints on either the image tag or on a preload for a given image would enable developers to signal the most important images for the user experience and cause them to potentially load sooner than they would otherwise. In Chrome, this could be done at the earliest stages of the HTML parsing and not rely on being able to re-prioritize requests that are already in-flight.

Signalling Relative API Priority

On fetch, specifically, all API calls for the same content type are treated equally. We have cases where we need to be able to make high-priority API calls in response to user input (type-down autocomplete for example) while there are also low-priority background API calls in-flight.

Priority Hints would allow developers to improve the multiplexing of the raw API calls and potentially get more responsive interactions in that situation.

Boosting the Priority of Async Scripts

By default, Chrome gives async scripts a relatively low priority because they do not block the parser. There are cases where those same async scripts are critical to rendering the user experience (common with loaders for app frameworks). There is a hack that developers currently use which is to add a preload for the same script which causes Chrome to boost the priority but it is a Chrome-specific hack that leverages side-effects of preload rather than an explicit signal.

Priority Hints would allow for a clean, explicit signal from a developer that a given script is important, even though it is not parser-blocking.

Spec Changes

I'd propose (and will submit a PR if discussions here support it) adding an importance attribute to:

  • <link>
  • <img>
  • <script>
  • <iframe>
  • ...any others? - maybe media tags for the autoplay initial load?

The HTML processing model itself is not expected to change, just the plumbing of the attribute on the elements to the underlying fetch (and no further than the fetch for the resource for the given element).

There is a corresponding issue in the fetch spec to track the underlying support in fetch.

Current Status in Chrome

Chrome is running an origin trial in Chrome 96+ (currently in Canary) with support for Priority Hints through HTML attributes and as an importance attribute on Request for fetch API calls to test the use cases listed above as well as the developer ergonomics around using the API.

There was an earlier origin trial in 2018 that was largely targeted at the use case of boosting async script priorities but the majority of partners in the trial had already implemented the script preload hack so there wasn't a lot of traction on it at the time. Since then, there have been other cases that have come up that don't already have existing hacks so hopefully we can get a cleaner read on it.

The last attempt also envisioned cascading the importance beyond the initial resource fetch to later work done by that resource (iframes, scripts, etc). That was beyond the scope of the working group's efforts and is no longer being explored. Priority Hints as implemented in the origin trial and as planned are expected to impact the fetching of the initial resource and nothing else (including execution).

@domenic
Copy link
Member

domenic commented Oct 4, 2021

I'd propose (and will submit a PR if discussions here support it) adding an importance attribute to:

It's unclear to me whether we should use a generic name like importance for something specific to fetch priority. Something more like fetchpriority="" or fetchimportance="" might make sense.

There's also the possibility of folding this into the general problem of "how to specify fetch options for HTML resources" that we've kicked around and never solved. (E.g. fetchoptions="mode: X, credentials: Y, cache: Z, integrity: W, importance: Q" or something.) Probably best not to block on that though.

@annevk annevk added addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest topic: fetch labels Oct 8, 2021
@smaug----
Copy link

I agree, "importance" sounds very generic, if this is really about loading resources only, like the draft proposal hints.
"importance" on an iframe could mean other things too, like how to prioritize the relevant process, and "importance" on an image could be about decoding etc.

@pmeenan
Copy link
Contributor Author

pmeenan commented Feb 2, 2022

@smaug---- agreed, but after 3-4 years of bikeshedding on it we haven't been able to come up with a better attribute/value combination that signals the developer intent (this is an important or less important image/script/frame) and still maintains a healthy disconnect from being to explicit about underlying scheduling or protocol-level priorities.

loading is currently used by lazyload and the existing eager and lazy don't overlay well with high and low priorities for loading (and the set of tags that loading covers is different).

fetch as an attribute was thrown around as a way to have a structured value pass settings through to an underlying fetch but that adds more developer complexity to the value itself.

loadingPriority is probably the closest to what it would do but is also pretty wordy and implies a tighter link to the protocol-level priorities than browsers are likely to actually offer.

For image decoding, we already have decoding (sync/async). For anything that implies task scheduling or or execution timing we are likely going to need more control than just importance. i.e. for script execution (to go with async) we will need to provide a mechanism to express when the execution should happen and if it should block DomContentLoaded or load.

For explicit frame prioritization I assume there is going to have to be similar discussions. For example, a video embed might be loaded at a low priority (or lazy) but once a user starts interacting with it, you likely want it to be as responsive as possible. That is part of why we pulled downstream effects out of priority hints itself - way too much chance to create a footgun with no clear need.

@smaug----
Copy link

loadingPriority sounds quite reasonable to me.

@addyosmani
Copy link

addyosmani commented Feb 16, 2022

agreed, but after 3-4 years of bikeshedding on it we haven't been able to come up with a better attribute/value combination that signals the developer intent (this is an important or less important image/script/frame) and still maintains a healthy disconnect from being to explicit about underlying scheduling or protocol-level priorities.

This would be aligned with my perspective as well. While importance is not a perfect attribute name, it has been socialized for enough years in the WebPerf community that I would be less concerned with it causing confusion now than I may have once been. That said, if there's a strong candidate that checks off all the boxes certainly not opposed.

loadingPriority is probably the closest to what it would do but is also pretty wordy and implies a tighter link to the protocol-level priorities than browsers are likely to actually offer.

One of the challenges with loadingPriority is that it falls down when scrutinized on the attribute length argument (importance = 10, loadingPriority = 15). Maybe priorityHint or loadPriority? It might also be useful to get perspectives from a few other WebPerf folks here.

@pmeenan
Copy link
Contributor Author

pmeenan commented Feb 16, 2022

Today in "naming things is hard"....

Priority hints spans both fetch and HTML so it's worth keeping both in mind when looking at the attribute names.

On the fetch side, Request already as a priority which is an opaque property that represents the browser's internal priority. Priority hints serve as an input when the browser decides how to set the priority but it isn't a direct connection (and priority isn't directly settable). On that side of things, importance feels like it is named well for the impact on the request.

The HTML side is where things get more complicated:

  • importance is a bit generic at an element level and may imply more scope than what it controls but it is directly aligned with the fetch attribute name and behavior which makes it a bit easier on devs (just one attribute to remember).
  • loadingPriority or fetchPriority are more inline with the behavior from the HTML side but also feel like they imply a direct connection to the priority property of the request rather than a connection to importance (or whatever the fetch side gets called).
  • fetchImportance would be a more descriptive and explicit attribute name with a direct line to the underlying fetch (technically it's attached to the request but it's close enough). It's a bit wordy but it's also different enough that it might be confusing.

There's existing examples for both matching attribute names (referrerpolicy and integrity are attributes on the same HTML elements that has the same request property names for fetch) and for differences (crossorigin vs credentials).

I'm still worried that anything with priority in the name is going to give devs the wrong idea about the level of control that the attribute carries and I like the reduced mental load of having the same attribute/property name across HTML and fetch but I'm happy to look at alternatives. I'd much rather get it "right" than rush it.

@domenic
Copy link
Member

domenic commented Feb 16, 2022

I'm still worried that anything with priority in the name is going to give devs the wrong idea about the level of control that the attribute carries

Can you explain this worry more? I think most devs don't have any idea that there are network-level priority stuff. That is, I don't think they have any expectations attached to the "priority" name besides the usual English connotations.

(I'm a reasonably advanced dev, and my vague understanding is that maybe HTTP/2 had something here, but it was inconsistently implemented and didn't work that great, so probably is no longer actually used, especially now that we've moved on to HTTP/3.)

@pmeenan
Copy link
Contributor Author

pmeenan commented Feb 16, 2022

Dev tools shows Chrome's internal priority as a column in the network tab. With HTTP 3 (and potentially retrofit to HTTP/2) there is the Extensible HTTP Priorities spec.

Probably the more direct issue is that there has been a regular ask to be able to explicitly specify priority order of resource fetching (compared to something like z-index). Setting an explicit priority on a given resource feels more "absolute" than a hint that plays into all of the other heuristics that also get applied.

@pmeenan
Copy link
Contributor Author

pmeenan commented Feb 18, 2022

@smaug---- @domenic if we get the topic on an upcoming w3c web performance working group meeting will you both be able to attend and help work through the naming?

Next few are:
Thursday March 3 - 11am ET / 8am PT / 4pm UTC
Thursday March 17 - 1pm ET / 10am ET / 5pm UTC
(they alternate times every 2 weeks beyond that)

For me, personally, there are 2 factors driving my preference for importance over anything priority

  1. Fetch has an opaque priority property on the Request interface that this will not control directly. This will set a different property that is used as an input when the browser sets the priority property internally.
  2. The passive "this is an important image/script/frame" attribution that goes with importance feels like a much better fit for what the API does than the more active load this image/script/frame at high priority that is implied with a priority attribute because it's just one of the factors that the browser will consider and the resulting priority may not be what was requested.

@smaug----
Copy link

March 17 should work for me. (too many overlapping meetings on March 3)

But I think the naming should be decided here. 'importance' doesn't hint at all what it is doing, yet it apparently verify specifically affects resource loading - that is why I don't like such a generic name.

@domenic
Copy link
Member

domenic commented Feb 18, 2022

if we get the topic on an upcoming w3c web performance working group meeting will you both be able to attend and help work through the naming?

I'd prefer to discuss asynchronously. To be clear, I'm just trying to clarify the issue here, and not expressing any blocking objections. @smaug---- is the most important one to get on board here. If you all get in a room and come to a decision, my job is done :)

  1. Fetch has an opaque priority property on the Request interface that this will not control directly. This will set a different property that is used as an input when the browser sets the priority property internally.

I don't think this is a concern. The internal fetch priority is not exposed to web developers and can be renamed at any time.

Overall I feel like you are bringing a lot of implementer/spec-reader perspective to this naming question and not enough web developer perspective. E.g. your (2) is similarly about factors the browser will consider. I'd encourage you to instead think of this from the web developer's perspective: e.g. "loading image1 is a higher priority to me than loading image2" seems very understandable. Whereas, "loading image1 is more important to me than loading image2" kind of makes it sound like there's a chance image2 won't load at all?

Of course my ability to channel web developers is imperfect, given that I too am steeped in specs and implementations and haven't developed serious web apps in a long time. So who knows if I'm right. But I think it's important not to discuss this from a spec/implementer perspective since that's just not relevant to these sorts of naming decisions.

This is separate from @smaug----'s concern, which seems to be about using any unadorned word (whether "importance" or "priority") without indicating the domain (e.g. with a "loading" prefix).

@pmeenan
Copy link
Contributor Author

pmeenan commented Feb 18, 2022

I'll try pulling in some more web devs for feedback and see how the broader community feels about the names. Twitter poll coming up (and hopefully some more comments here).

@pmeenan
Copy link
Contributor Author

pmeenan commented Feb 18, 2022

Poll is up if you'd like to follow along over the next few days, otherwise I'll report here when it is done.

@andydavies
Copy link
Contributor

@pmeenan Going back to your initial post do you see a way to make this work with the poster image in

I'm thinking of the case where someone wanted to hint that the poster is high priority for LCP reasons, but not wanting the video to autoplay

@pmeenan
Copy link
Contributor Author

pmeenan commented Feb 18, 2022

@andydavies preload (with hints) for the poster image is an easy way to do it. I haven't put much thought into the video element itself though (particularly if it is autoplay vs not).

@tunetheweb
Copy link
Contributor

tunetheweb commented Feb 18, 2022

Pardon my ignorance, but does the HMTL markup need to so intrinsically linked to what is done with it (Priority Hints)?

The clue (or hint!) is in the name ("hint"), so it’s a suggestion not an instruction.

Given that, importance="high" markup could in theory be a signal for lots of things for the browser to do:

  • Boost its fetch priority (i.e. its request priority) - aka Priority Hints.
  • Boost it’s HTTP/2 or HTTP/3 priority (i.e. it’s recommended sending back priority) - aka h2/h3 prioritisation.
  • Set exclusive bit in HTTP/2 priority (or something similar, in the simpler H3 model like downgrading other priorities).
  • Use the high speed connection if a device has multiple connections in the future when we'll laugh at the thought of one connection.
  • Decoding options (though agree with your point about decoding already existing to that).
  • Ramp up CPU when applied to a <script> tag.
  • Whatever else the future brings!

So I like importance explicitly because it doesn’t just limit it to priority hints (case 1).

I get it’s generally preferred to be explicit what an attribute does and means, but markup is markup and should be separate to implementation IMHO.

<strong> is preferred over <b> these days since markup is interested in the semantics of what that element means, rather than how the browser chooses to act upon that information and style it to try to reflect those semantics.

Isn't it the same here? Isn't the implication the element is important and should be treated as such by the browser, rather than it must use Priority Hints to process this element?

@sean-roberts
Copy link

"Importance" seems too loaded + ambiguous and applicable to so many contexts that it becomes unclear what this attr will impact.

Why not just 'priorityHint'? It being a hint already offers that it can be used by other features to understand how the resource relates to others in priority and can all of the other mention potential tooling. So for any feature that may benefit from a hint in the priority of a resource can.

@zcorpan
Copy link
Member

zcorpan commented Feb 18, 2022

On the hint-ness, it's not uncommon for HTML attributes to be hints without the attribute name conveying that. For example: type, autocapitalize, decoding, preload, autoplay, playsinline, accept, autocomplete.

The only attribute with hint in the name is enterkeyhint (maybe it should have been called enterkey?).

priority could apply to other things, but the same could be said for type, integrity, media, and so on. HTML would be much more verbose if all attribute names were more wordy.

Since the fetch "priority" concept is not web-exposed, we shouldn't be concerned about it when naming web-exposed features. If people are confused, the internal concept can be renamed.

@pmeenan
Copy link
Contributor Author

pmeenan commented Feb 18, 2022

I'll give it through Monday to collect feedback but it looks like fetchPriority is probably going to take it from the twitterverse (granted, my corner of it but that tends to be a pretty good sample of the web performance space).

@smaug---- would you be OK with fetchPriority for the HTML attribute and priority for the Request object property on the fetch JS API (renaming the existing opaque priority to internalPriority or something like that since it's not web-exposed and just part of the spec)? That way the HTML and fetch attribute names would be aligned.

@nemzes
Copy link

nemzes commented Feb 19, 2022

(bike-shedding prompt via Twitter)

Having read the arguments above, I agree that simply priority is probably the most understandable from a web developer's perspective. Is it too generic? In the context of the HTML elements, I don't think so. The main function of those elements is to load an external resource; it follows that "priority" is most understandable as a characteristic of that function (i.e. "the priority of losing the resource") so it should not need extra qualifiers.

Another good alternative could be precedence.

As an aside: multi-word HTML attributes are harder to understand (especially to non-native English speakers) since they are case-insensitive and it's not always obvious where word boundaries are. Also, a lot easier to misspell.

@smaug----
Copy link

fetchPriority on elements and priority on the request sounds quite reasonable.

@pmeenan
Copy link
Contributor Author

pmeenan commented Feb 28, 2022

FYI, the attribute name changes have been merged into the priority hints spec. For the HTML elements it is using fetchpriority and for fetch() it is using the priority property on Request.

Everything else holds the way it was with importance:

  • high, low and auto for the values for the attribute/property
  • hint for the browser to use when determining actual priority
  • only applies to the fetch for the main resource for the element, not subresources, scheduling, etc

@pmeenan
Copy link
Contributor Author

pmeenan commented Nov 1, 2022

Chrome has shipped this in 103.

@valenting can you comment on Mozilla's interest as a second implementor?

@valenting
Copy link

I think the spec in its current state is quite reasonable.
The Gecko networking team intends to implement this in early 2023.

@domenic domenic removed the needs implementer interest Moving the issue forward requires implementers to express interest label Feb 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
addition/proposal New features or enhancements topic: fetch
Development

No branches or pull requests