5

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?

Jeroen
  • 60,696
  • 40
  • 206
  • 339

1 Answers1

0

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;
  });
});
Evert
  • 93,428
  • 18
  • 118
  • 189
  • 1
    Hmm, from the docs I understood that [`preload` is meant to do stuff before JS execution / DOM ready](https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content) and that [`prefetch` is used for something that might be needed soon, but does not block the page](https://www.w3.org/TR/resource-hints/#speculative-resource-prefetching-prefetch). - Thx for your response nonetheless, your way is certainly a useful one too! Would've used it, except that Chrome Mobile also _did_ turn out to work with `prefetch`, and that's my target audience anyways, so I'll stick with my question's approach. – Jeroen Jan 07 '20 at 13:12