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 #3670

Closed
domfarolino opened this issue May 6, 2018 · 18 comments
Closed

Standardize Priority Hints #3670

domfarolino opened this issue May 6, 2018 · 18 comments
Labels
addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest needs tests Moving the issue forward requires someone to write tests

Comments

@domfarolino
Copy link
Member

domfarolino commented May 6, 2018

Discussion

Priority Hints is an API that lets developers signal to the browser the relative importance of a resource to a page, 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 H2 priority, delaying when a request is sent out, etc.

Developers have expressed interest in an API that lets them guide the browser's native prioritization logic in cases where the developer might know better than the browser, which resources are more important to a page than others. The spec describes a new attribute named importance that can be applied to some resource-fetching HTML elements (as well as the fetch() API). The attribute can take the value of auto, low, or high, as currently denoted in the explainer spec. The attribute is just a hint, similar to image decoding. I propose supporting this importance hint on the following elements:

  • <link>
  • <img>
  • <script>
  • <iframe>
  • ...others that make sense?

I'm owning the implementation of Priority Hints in Chrome, and it seems like it'd be good to try and gauge interest in this from other implementers and work on getting this standardized. IIRC, Priority Hints has gotten good feedback at TPAC, but @addyosmani can speak more for this.

/cc @addyosmani @yoavweiss @yutakahirano @bzbarsky @wanderview (other...?)


Spec Questions/Work

Assuming this seems like a good idea to the editors, I'm happy to lead the standardization effort of this both here and in the Fetch Standard. Here are a few questions I have at the moment regarding potential spec changes:

  • It seems that the attribute can be spec'ed as an enumerated attribute with missing & invalid value defaults as the auto mode. Seeing as how it spans multiple resource-fetching elements, it seems like a good idea to include it in the URLs & Fetching section, like the CORS settings attributes, is this the right idea?
  • (Also it seems it'll need to appear in the IDL of the list of supported resource-fetching elements that appear above, as well as their processing models where the importance can be communicated to the Fetch Standard)
  • Subresources

    • We'd like the importance value of scripts and iframes to trickle down to their subresources. I haven't dug around enough myself, but if someone could point me to where in the spec we can acknowledge properties of the parent element of subresources that would be nice.
  • Module Scripts

    • I know that loading modules has some different infrastructure, and preloading, due to this infra, was different-enough to warrant the creation of the rel value modulepreload, so I'm wondering what work will need to be done here in the fetching of a module graph.
  • I'll can follow up with an issue on the Fetch Standard to determine what changes will need made there, so we can discuss that here and I can just submit a PR separately (since the changes should be relatively small compared to those here).
@annevk annevk added addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest needs tests Moving the issue forward requires someone to write tests labels May 7, 2018
@domenic
Copy link
Member

domenic commented May 7, 2018

Seeing as how it spans multiple resource-fetching elements, it seems like a good idea to include it in the URLs & Fetching section, like the CORS settings attributes, is this the right idea?

Agreed.

if someone could point me to where in the spec we can acknowledge properties of the parent element of subresources that would be nice.

This seems generally hard, and somewhat unprecedented. Maybe @annevk has more of an idea.

One idea that comes to mind is to have the Fetch layer take care of this. So, add an algorithm to all environment settings objects to determine the default priority hint for that environment settings object (= realm = global). Then, if fetch sees "auto", it consults the request's client's default priority hint.

I'm wondering what work will need to be done here in the fetching of a module graph.

All of the module script fetching is centralized in https://html.spec.whatwg.org/multipage/webappapis.html#fetching-scripts. You'll want to add something to the script fetch options struct, and update all places that construct instances of that struct.

@annevk
Copy link
Member

annevk commented May 8, 2018

What is a subresource of a script? As far as I can tell that kind of thing only works for imports. Anything else you don't really know what script it belongs to. (Worker scripts are different of course, perhaps you want this for them too?)

For <iframe> I think the thing you want to do is to copy the state to the document. So documents need to carry some global state (and maybe workers too) that everyone looks at before looking at their local state. Very similar to referrer policy and such.

@domfarolino
Copy link
Member Author

Thanks for the insights @domenic. That sounds good at the Fetch layer.

Then, if fetch sees "auto", it consults the request's client's default priority hint.

The more I think about this the more tedious it seems it could become (for implementations), recursively looking at each request's client's priority hint wherever a default is found until we get either a non-default hint or a top-level client, but I guess that is sensible.

Ah yes, the script fetch options struct, I've definitely seen that before. Perfect.

@annevk Well I guess it would be nice to have things like:

  • fetch()
  • document.createElement('img').src = 'test'

...(maybe others) honor the <script>'s importance value if it exists. Not sure if this is entirely desirable or possible though. Extracting a hint via an environment settings object at the Fetch level (like in step 5 of main fetch) as previously mentioned seems to make this impossible, since we wouldn't have a way to determine in Fetch, that the request originated from a <script> to take a different action. For example, w3c/webappsec-referrer-policy#96 doesn't imply that the "subresources" I allude to will be requested with <script>s referrerpolicy, but instead will be requested with the script's node document's Window object's environment settings object's referrer policy...that is a mouthful. So it seems we might not be able to/want to support this.

@annevk
Copy link
Member

annevk commented May 9, 2018

How do you define originating <script>? That is not a concept we have.

@domfarolino
Copy link
Member Author

The <script> element in the following snippet would be what I loosely think as the "originating script":

<script importance=low> <!-- script is fetched with importance=low -->
    fetch("someResource"); // fetched as if RequestInit contains {importance: 'low'} due to the "parent" script
</script>

But I'm not sure how feasible this is. I guess to do this, we'd have to modify every place where we set request's client to an environment settings object to copy the previously-used environment settings object, and replace its importance with a paren't script's importance, if said parent exists, which seems really messy and not good. Plus again, referrer policy (once added to <script>s) will not behave in this way.

@annevk
Copy link
Member

annevk commented May 9, 2018

@domfarolino what about

<script importance=low> function lala() { return fetch("someResource"); } </script>
<script> lala(); </script>

? (To be clear, this has been discussed a number of times and nobody really wants to do the kind of stack tracing and JavaScript engine overhaul that'd be required.)

@domfarolino
Copy link
Member Author

domfarolino commented May 9, 2018

That's a good question. That's something I missed bringing up in WICG/priority-hints#24 as I was looking for more complicated examples. I'm not really sure about that one honestly, and I'm sure we can find even more complicated situations than that. It sounds like we shouldn't do trickle-down request prioritization for requests made within scripts (for consistency and ease of adoption), would you agree?

Edit

Since accessing document.currentScript in that example from within the lala function would yield the script without importance, I guess there'd be no importance to trickle down in that case, but I'm really not sure if that's a good idea, or helps us out at all.

@annevk
Copy link
Member

annevk commented May 9, 2018

Note that there's no document.currentScript for module scripts. And yeah, I don't think we want to be doing this.

@bzbarsky
Copy link
Contributor

I don't think we want any loads triggered by a script, in perpetuity, inheriting the priority of the script, even if we could define how that would work. It seems quite reasonable to have a high-priority script that you want loaded quickly because it builds your UI, but that doesn't necessarily mean that you want every single resource load in that UI to be high-priority. In fact, chances are you don't.

For subframes the situation is also complicated. In particular, I can see prioritizing whatever gets the subframe to firing a load event, but going back to normal priority after that... Otherwise you would probably never want to use a priority hint on any iframe that has long-lived content that keeps making requests.

For the rest, I'm not sure whether the low/auto/high setup maps well to all UAs internal prioritization schemes. @mcmanus probably has a better idea of how this works in firefox nowadays or who would know.

@domfarolino
Copy link
Member Author

domfarolino commented May 11, 2018

It seems quite reasonable to have a high-priority script that you want loaded quickly because it builds your UI, but that doesn't necessarily mean that you want every single resource load in that UI to be high-priority

That's a good point.

I can see prioritizing whatever gets the subframe to firing a load event, but going back to normal priority after that

Hmm, yeah, there are certainly a lot of miscellaneous requests a frame might make, but I guess that would be the developer's choice whether it would be worth prioritizing the whole frame or not. There seems to be two problems here:

  • The first is that non-importance-adorned requests would automatically inherit importance=high, which might cause regressions in the parent page.
  • Second is, requesting in a frame, a page that uses priority hints basically makes those inner hints useless. For example, say in an <iframe> we request a page that fetches three images with importance=low. The developer of that inner page clearly meant for these to not be prioritized high, but our model ignores this, also maybe causing regressions.

I know I've talked with @addyosmani and @KenjiBaheux about having the parent's importance take precedence, but if we only let it take precedence when the parent has importance=high. In other words, subresources can always lower their importance by overriding, but can never raise it? Just a thought... This doesn't fix the case where regular non-importance-adorned `

@jakub-g
Copy link

jakub-g commented Nov 15, 2018

I'm late to the party, but let me add my two cents from web perf developer point of view.

Video platforms like YouTube, Dailymotion, Vimeo etc. have <iframe> embed endpoints.
The embeds typically contain a bunch of JS, some CSS, a poster image, and a video stream.

Those embeds are included in the 3rd party websites, and some of those websites might want to have the video loaded as fast as possible.

On the other hand, many of those parent pages also have dozens or even hundreds of subresources.
The final effect is that the requests from parent page and from the iframe are intermixed, resulting in slow load time of the frame, much slower than in isolation.

Hence <iframe importance=high> could be a big win for those kind of pages.

For subframes the situation is also complicated. In particular, I can see prioritizing whatever gets the subframe to firing a load event, but going back to normal priority after that...

Sounds good to me 👍

Second is, requesting in a frame, a page that uses priority hints basically makes those inner hints useless. For example, say in an <iframe> we request a page that fetches three images with importance=low. The developer of that inner page clearly meant for these to not be prioritized high, but our model ignores this, also maybe causing regressions.

Very good point, that would be very tricky and counter-intuitive indeed if content would load in a wildly different way when wrapped vs in isolation.
The relative priorities inside the iframe should definitely be kept if possible.

@domfarolino
Copy link
Member Author

In Chrome, our current implementation has not shown benefits in early experimentation, and unfortunately there are no immediate plans for going back to the drawing board and re-experimenting. Since nothing in this issue is actionable, and we're probably blocked on Chrome trying to show a benefit for this feature, I'll close this, and re-open if/when necessary.

@jeffreytgilbert
Copy link

Should this resurface in the future, properties the parent document declared should not be applied to the child or third party iframe. Each document should be responsible for its own load order and priority related to assets. I understand applying security and sandboxing constraints on a content container. I don't understand applying load order priority for a document operating in its own sandboxed space. That seems like the sort of contract you want to allow linked documents to opt into rather than something you foist on them.

@drzraf
Copy link

drzraf commented Aug 2, 2021

I don't understand why was this closed.

has not shown benefits in early experimentation

That's all?

I've a use-case uploading a chunked file (a couple of parallel fetch) + some metadata (whose upload is initiated later but must have a higher priority). Priority-hints solves this exact problem.

@jeffreytgilbert
Copy link

@drzraf pretty sure this was canned by all browsers for a different implementation. It looks like only IE 11 adopted it.

https://caniuse.com/lazyload
Which points to this as the replacement:
https://caniuse.com/loading-lazy-attr

@addyosmani
Copy link

In Chrome, we continue to be interested in providing developers greater control over relative resource loading priorities, but have not yet been able to define changes to the original Priority Hints spec draft that we believe give developers the kinds of wins they might expect. That is not to say that Priority Hints are off the table, but we need to refine their value to the point another round of experimentation could be done (in a world where you also have preload, early hints etc).

@pmeenan
Copy link
Contributor

pmeenan commented Oct 1, 2021

I'm taking over work on reviving the Priority Hints experiment in Chromium and it is currently set for origin trial in Chrome 96 (canary as of right now).

Is it better to re-open this issue and assign it to me or start with a new issue and reference this one from it?

There is no cascade/inheritance/persistence of the attribute as currently spec'd or implemented and that's probably for the better. For the embeds case, there is already lazyload support for frames and once the embedded content is actually being interacted with you likely want it to behave normally.

The importance attribute is implemented for any DOM elements that trigger a fetch (scripts, images, stylesheets, preloads, audio, video, etc) as well as as an attribute on Request for fetch calls from Javascript.

The concrete use cases we have where we can demonstrate benefits right now are:

  • Boosting the priority of critical images (hero image in particular).
  • Boosting the priority of async scripts that are actually render-blocking for the site (or otherwise critical) without using the script preload hack that just works because of Chrome-specific side-effects.
  • Lowering the priority of script preloads to improve discovery of lower-priority scripts without blocking critical content.
  • Differentiate fetch() calls for responding to user input (type-down suggestions for example) vs background API activity.

At least in Chrome, tweaking the priority of a few elements one way or another can have a large impact on the resulting performance in ways that aren't currently possible without a lot of browser-specific hacks (leveraging side-effects of ordering, preload, etc). Here is the impact to Fox News for example by boosting the hero image priority.

@annevk
Copy link
Member

annevk commented Oct 4, 2021

I think a new issue describing things as they are today would be great.

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 needs implementer interest Moving the issue forward requires implementers to express interest needs tests Moving the issue forward requires someone to write tests
Development

No branches or pull requests

10 participants