103 Early Hints - what file types can leverage them?

When writing the Early Hints Worker, I added in the 3 valid 'as' attributes that I know of - image, script and style. This worked just fine for my use-case as I only intended to preload those assets, but I was curious as to what else can leverage Early Hints.

A post on the Cloudflare community led me to dig a bit deeper as to which link attributes are taken into consideration for Early Hints.

I also see mention of an issue with Cloudflare and media link headers that one person had. I will test another version with type and where media is based on the Chrome 104 syntax of > instead of : .

Does media work with Early Hints? My usual go-to is the relevant RFC. In this case, it's RFC8297 and all you get it some generic examples of a link header that just use rel and as. So it isn't explicitly mentioned that media is supported, but it also isn't mentioned that it isn't.

My curiousity isn't satisfied with that - so we keep on digging. There's some further information in the WHATWG HTML Standard WebIDL so let's take a look there.

Bingo - this is what we was looking for. media isn't taken into consideration since Early Hints uses link headers rather than link tags in the document.

So, that answers my question about what other attributes are supported - but what about the valid values for the as attribute? Can we preload more than images, scripts & stylesheets? Let's click on as in the above screenshot!

This takes us to potential destination - which then takes us to destination. Here's where we find the 'enumated attribute' values.

A request has an associated destination, which is the empty string, "audio", "audioworklet", "document", "embed", "font", "frame", "iframe", "image", "manifest", "object", "paintworklet", "report", "script", "serviceworker", "sharedworker", "style", "track", "video", "worker", or "xslt". Unless stated otherwise it is the empty string.

There's a lot of them! But, like I said before, I'm interested in which ones work with Early Hints specifically and we've already experienced a scenario where they're only valid in link tags, not link headers.

At the time of writing, Chrome 103 & above is the only browser that supports Early Hints so let's go have a dig through the source code there since Chromium is an open-source project. Using Chromium Code Search & searching for early_hints led me here:

link_header.mojom.h sounds like it might be what I'm interested in, but let's take a look at this file content/browser/loader/navigation_early_hints_browsertest.cc

  HeaderField CreatePreloadLinkForScript() {
    return HeaderField(
        "link",
        base::StringPrintf("<%s>; rel=preload; as=script", kHintedScriptPath));
  }

  HeaderField CreatePreloadLinkForCorsScript() {
    return HeaderField(
        "link", base::StringPrintf("<%s>; rel=preload; as=script; crossorigin",
                                   kHintedScriptPath));
  }

  HeaderField CreateModulePreloadLink() {
    return HeaderField("link", base::StringPrintf("<%s>; rel=modulepreload",
                                                  kHintedScriptPath));
  }

  HeaderField CreatePreloadLinkForStylesheet() {
    return HeaderField("link", base::StringPrintf("<%s>; rel=preload; as=style",
                                                  kHintedStylesheetPath));
  }
https://source.chromium.org/chromium/chromium/src/+/main:content/browser/loader/navigation_early_hints_browsertest.cc;l=213?q=early_hints&ss=chromium%2Fchromium%2Fsrc

It looks like they're testing script and style - where's image? That's referenced a bit further down.

  HeaderField link_header = HeaderField(
      "link", base::StringPrintf("<%s>; rel=preload; as=image",
https://source.chromium.org/chromium/chromium/src/+/main:content/browser/loader/navigation_early_hints_browsertest.cc;l=841?q=early_hints&ss=chromium%2Fchromium%2Fsrc

If we go and take a look at the header file for link headers overall, services/network/public/mojom/link_header.mojom, we can see which of the ~19 'destinations' are actually valid as attributes.

// Represents subset of possible values for `as` attribute of the Link header.
enum LinkAsAttribute {
  kUnspecified,
  kFont,
  kImage,
  kScript,
  kStyleSheet,
};
https://source.chromium.org/chromium/chromium/src/+/main:services/network/public/mojom/link_header.mojom;drc=ba884f9cab8d36478acb75ad668280e05b61fb1c;bpv=1;bpt=1;l=20

So Chromium will only really consider font, image, script and style. My curiousity is satisfied!

It's always fun to pick resources apart and find exactly what you're looking for. Each step gave another hint as to where to look, and the beauty of open source software means that we can just take a look as to what Chrome is doing as opposed to trying to reverse engineer or test it ourselves!