Add response header from HTMLRewriter worker

I’m trying to implement Early Hints via service worker to preload images. The images that need to be preloaded are figured out by HTMLRewriter.

Is there any way to add a response header from HTMLRewriter? (to add these images as Link response header)

class ElementHandler {
  element(element) {
    console.log(`Incoming image: ${element.getAttribute('src')}`);
    // Add this image to response header (as link)
  }
}

async function handleRequest(req) {
  const res = await fetch(req);

  return new HTMLRewriter().on('img[loading=eager]', new ElementHandler()).transform(res);
}

You’ll want to have an array that you’re pushing the src attribute into which you can later loop over to construct your link header.

Pseudo:

const imgs: string[] = []
const transformed = new HTMLRewriter()
  .on("img", {
    // get src attribute - check if it exists
    imgs.push(src);
  })

imgs won’t actually have anything until you either await the body of transformed or return a response - the joys of async. Since we want to populate imgs in order for us to construct the link header in our response then we can do const body = await transformed.text() which gives us the HTML body of our original request as well as ‘runs’ the ElementHandler so imgs actually has content now.

You can then iterate over imgs using forEach and construct your link header - the link header is comma-separated so you’ll want to take that into consideration and make sure that your final entry doesn’t end in an un-necessary comma.

1 Like

It also goes without saying that you might want to scope your preload assets - not every image, i.e lazy loaded ones, should be preloaded.

Recommendations from https://blog.cloudflare.com/early-hints-performance/

  • Preconnect Link headers to important third-party origins (e.g. an origin hosting the pages’ assets, or Google Fonts).
  • Preload Link headers for a handful of critical render-blocking resources.
  • Scripts and stylesheets split into chunks, enumerated in preload
  • A preload Link for the LCP asset, e.g. the featured image on a blog post.
1 Like