Learn Performance - Prefetch and Prerender

Prerender

It is possible to prerender URLs using speculation rules. This page will add speculation rules to prerender the URL /4-prerender when the user hovers over the link for 200ms—indicating an intent to click.

Go to prerendered page

Note that this might not work on touch devices.

Prerendered resources are visible in Chrome DevTools network tab by changing the renderer to the prerendered URL.

Chrome DevTools Network panel showing 4 resources for the prerendered document.

In the Network panel above, the resources required to prerender the URL 4-prerender are visible in Chrome DevTools.

It is also possible to debug prerendered URLs using Chrome DevTools Application panel. On the left-hand side, there should be the option to select Speculation Rules or Preloads.

Chrome DevTools Application panel showing a prerendered resources.

The above Application panel shows that the URL /4-prerender was prerendered and is available for navigation.

View Source Code
function isSameOrigin(origin, path) {
  if (path.indexOf("http") !== 0) {
    return true;
  }

  const url = new URL(path);
  return url.origin === origin;
}

function addSpeculationRules(target) {
  const specScript = document.createElement("script");
  specScript.type = "speculationrules";
  specScript.textContent = `
    {
      "prerender": [
        {
          "source": "list",
          "urls": ["${target}"]
        }
      ]
    }`;
  document.body.appendChild(specScript);
}

const handleMouseOver = (n) => (m) => {
  const targetUrl = m.target.getAttribute("href");

  let timeout = setTimeout(() => {
    if (targetUrl && isSameOrigin(location, targetUrl)){
      addSpeculationRules(targetUrl);
      timeout = 0;
    }
  }, 200);

  // do not add spec rules if the cursor leaves before 200ms
  n.addEventListener("mouseleave", () => {
    if (timeout) {
      clearTimeout(timeout);
      // re-add the listener if the spec rule was not added
      n.addEventListener("mouseover", handleMouseOver(n), { once: true });
    }
  }, { once: true });
}

// add speculationrules if the user hovers over a link element
document.querySelectorAll("a[href]").forEach(n => {
  n.addEventListener("mouseover", handleMouseOver(n), { once: true });
});