Using "prefetch" links for images in Chrome

862 Views Asked by At

Suppose the following snippet:

document.addEventListener("DOMContentLoaded", () => {
  const src = "https://via.placeholder.com/200x100?text=loaded";
  
  const link = document.createElement("link");
  link.rel = "prefetch";
  link.as = "image";
  link.href = src;
  document.head.append(link);
  
  document.getElementById("btn").addEventListener("click", () => {
    document.getElementById("img").src = src;
  });
});
<button id="btn">Press me to show prefetched image (but go offline first!)</button>
<br><img id="img" src="" alt="press button to load prefetched image">

Firefox 71, offline using the Web Developer Tools, then press the button, the image loads perfectly. I expected as much, as the Network tab in the Developer tools showed the prefetched image.

Chrome 79, offline using the Network Dev Tools, then press the button, the image doesn't load. I suspected as much, because the Network tab shows weird entries for the prefetches.

Most resources, most notably caniuse.com, notice cross-browser support for prefetch of images, with no known issues. So I must be off with my reasoning somewhere.

Here's what the requests look like in Chrome:

network tab showing failed request

and the prefetch request expanded:

not loaded image preview

What am I doing wrong?

1

There are 1 best solutions below

1
On

The main purpose of prefetch is to tell a browser to start grabbing things as soon as the first bytes of your html have arrived (or better yet, HTTP headers). This happens even before javascript starts executing or the DOM is ready. Using it dynamically with javascript doesn't make a ton of sense.

So I'm very much not surprised that (some) browsers don't listen for <link> changes and load things as they are added to that list. I'm very surprised that Firefox does this at all.

To prefetch an image, you can just use the traditional method:

document.addEventListener("DOMContentLoaded", () => {
  const src = "https://via.placeholder.com/200x100?text=loaded";

  const img = new Image();
  link.src = src;

  document.getElementById("btn").addEventListener("click", () => {
    document.getElementById("img").src = src;
  });
});