Search code examples
htmlprefetchprerender

The fantastic but confusing idea of Resource Hints: (a)synchronous?


I've been reading through Google's slides for the so-called pre-optimisation. (For the ones interested or for those who do not know what I'm talking about, this slide kinda summarises it.)

In HTML5 we can prefetch and prerender pages in the link element. Here's an overview. We can use the rel values dns-prefetch, subresource, prefetch and prerender.

The first confusing thing is that apparently only prefetch is in the spec for HTML5 (and 5.1) but none of the others are. (Yet!) The second, that browser support is OK for (dns-)prefetch but quite bad for the others. Especially Firefox's lack of support for prerender is annoying.

Thirdly, the question that I ask myself is this: does the prefetching (or any other method) happen as soon as the browser reads the line (and does it, then, block the current page load), or does it wait with loading the resources in the background until the current page is loaded completely?

If it's loaded synchronously in a blocking manner, is there a way to do this asynchronously or after page load? I suppose with a JS solution like this, but I'm not sure it will run asynchronously then.

var pre = document.createElement("link");

pre.setAttribute("rel", "prerender prefetch");
pre.setAttribute("href", "next-page.php");

document.head.appendChild(pre);

Please answer both questions if applicable!

EDIT 17 September

After reading through the Editor's draft of Resource Hints I found the following (emphasis mine):

Resource fetches that may be required for the next navigation can negatively impact the performance of the current navigation context due to additional contention for the CPU, GPU, memory, and network resources. To address this, the user agent should implement logic to reduce and eliminate such contention:

  • Resource fetches required for the next navigation should have lower relative priority and should not block or interfere with resource fetches required by the current navigation context.
  • The optimal time to initiate a resource fetch required for the next navigation is dependent on the negotiated transport protocol, users current connectivity profile, available device resources, and other context specific variables. The user agent is left to determine the optimal time at which to initiate the fetch - e.g. the user agent may decide to wait until all other downloads are finished, or may choose to pipeline requests with low priority if the negotiated protocol supports the necessary primitives. Alternatively, the user agent may opt-out from initiating the fetch due to resource constraints, user preferences, or other factors.

Notice how much the user agent may do this or that. I really fear that this will lead to different implementations by different browsers which will lead to a divergence again.

The question remains though. It isn't clear to me whether loading an external resource by using prefetch or other happens synchronously (and thus, when placed in the head, before the content is loaded), or asynchronously (with a lower priority). I am guessing the latter, though I don't understand how that is possible because there's nothing in the link spec that would allow asynchronous loading of link elements' content.


Solution

  • Disclaimer: I haven't spent a lot of dedicated time with these specs, so it's quite likely I've missed some important point.

    That said, my read agrees with yours: if a resource is fetched as a result of a pre optimization, it's likely to be fetched asynchronously, and there's little guarantee about where in the pipeline you should expect it to be fetched.

    The intent seems advisory rather than prescriptive, in the same way as the CSS will-change attribute advises rendering engines that an element should receive special consideration, but doesn't prescribe the behavior, or indeed that there should be any particular behavior.

    there's nothing in the link spec that would allow asynchronous loading of link elements' content

    Not all links would load content in any case (an author type wouldn't cause the UA to download the contents of a mailto: URL), and I can't find any mention of fetching resources in the spec apart from that in the discussion around crossorigin:

    The exact behavior for links to external resources depends on the exact relationship, as defined for the relevant link type. Some of the attributes control whether or not the external resource is to be applied (as defined below)... User agents may opt to only try to obtain such resources when they are needed, instead of pro-actively fetching all the external resources that are not applied.

    (emphasis mine)

    That seems to open the door for resources specified by a link to be fetched asynchronously (or not at all).