Service Worker Caching

I've always been impressed by QwikCity and the way it makes use of Service Workers to cache resources. The speed you get from it is incomparable to other frameworks.

However, while it is the only one I know of that uses service worker caching out of the box. It turns out this is very easy to implement with vanilla JS.

Service workers have a simple fetch event that allow you to listen to all incoming requests which is the perfect place to make use of Cache API. This interception in a service worker would look like this:

self.addEventListener("fetch", onFetch);

function onFetch(event) {
  event.respondWith(router(event.request));
}

async function router(request) {
  const url = new URL(request.url);
  const requestUrl = url.pathname;
  const cache = await caches.open(cacheName);

  if (url.origin === location.origin && request.method === "GET") {
    let response;

    try {
      response = await cache.match(requestUrl);

      if (response) {
        return response;
      }
    } catch (error) {}

    const fetchOptions = {
      method: request.method,
      headers: request.headers,
      credentials: "omit",
      cache: "no-store",
    };

    response = await fetch(requestUrl, fetchOptions);

    if (response && response.ok) {
      await cache.put(requestUrl, response.clone());
      return response;
    }
  }

  return fetch(request);
}

This looks like a lot of code, but the idea is very simple. With all GET requests that match the current domain origin, try to find the cached response in Cache API. Otherwise, fetch it from the server.

The results are very fast navigations with server rendered HTML. As you navigate this site, which now uses this service worker, load times feel near instant. But there is no SPA, only the above code. Plus it has the added benefit of making previously visited pages available offline.

You can find this code in its entirety in the initialization script and the actual worker script.