Improvement 1: Preloading
After step 3, we can make a clever little move: preload the version we’re soon
going to force the user onto. If the app is just one JavaScript bundle, you can
use rel=“preload”:
function preload(url, type) {
var preloadLink = document.createElement("link");
preloadLink.href = url;
preloadLink.rel = "preload";
preloadLink.as = type;
document.head.appendChild(preloadLink);
}
preload("/ny-app.js", "script");
This assumes that you know the URL of the new version: either it’s static (not
so good for caching), or the URL can be calculated with the version string, or
the version endpoint returns data that provides the URL, for example:
{
"appFile": "/bundles/e35fe20b.js"
}
If the app consists of several script files, and maybe a CSS file or two, you
can still use the technique above, just include a list of resources to preload
instead:
version.appResources
.forEach(resource => preload(resource.url, resource.type));
A cheeky brute-force approach to preloading is to fetch the entire app in an
invisible iframe that you remove as soon as it’s loaded:
frame = document.createElement("iframe");
frame.src = "/";
frame.style.width = 0;
frame.style.height = 0;
frame.addEventListener("load", () => document.body.removeChild(frame));
document.body.appendChild(frame);
This suggestion should perhaps be taken with a grain of salt as you’ll be
running a fully functioning client in the background (even though it’s removed
again).