What Web Can Do Today?

Can I rely on the Web Platform features to build my app?

An overview of the device integration HTML5 APIs

Offline Mode

Web applications can provide the offline experience using two techniques. The older implementation, Application Cache, is widely implemented in the browsers, but is now in the process of deprecation due to various conceptual and design flaws. It is not covered here.

The modern alternative is called Cache API and is available within Service Worker – the separate code unit the Web applications running on HTTPS can request the browser to install. This unit is then run in separation from the owning Web application, communicating with it via events. Service Worker is the basic building block of the Progressive Web Apps (PWA) idea. Besides being the enabler for multiple complex APIs like Push Notifications, Background Sync or Geofencing, it can work as a fully featured network proxy. It can intercept all the HTTP requests, alter its content or behaviors, or - most notably - manage offline caching.

The content being added to Cache API might be additionally indexed and exposed to the browser using Content Indexing API. As of Spring 2020, this is an early-stage proposal by Google Chrome, available only in this browser on Android via Origin Trial experimentation. The entries added to the index should be cached in Cache API and served offline via Service Worker. The browser might then present the indexed entries for the user while being offline.

API glimpse

Within the owning Web application - Installation

navigator.serviceWorker.register(path)
Installs the Service Worker code available under path. Returns a Promise.
navigator.serviceWorker.ready
Returns a Promise resolved with serviceWorkerRegistration when the Worker is initialized.
serviceWorkerRegistration.update()
Checks the server for an updated version of the Service Worker without consulting caches.
serviceWorkerRegistration.unregister()
Uninstalls the Service Worker.

Within the Service Worker instance - Cache prefetch

self.addEventListener('install', function (event) {
  event.waitUntil(
    caches.open('my-cache-v1')
      .then(function (cache) {
        return cache.addAll(['/', '/styles/main.css', '/scripts/main.js']);
      })
  );
});
self.addEventListener('install', listener)
An event fired within the Service Worker when it is being installed. Useful to prefetch the resources needed in the offline mode and to prefill the cache.
event.waitUntil(promise)
An install event method that expects a Promise which signals the end of the worker's installation phase when resolved.
caches.open(cacheName)
Returns a Promise resolved with the named cache accessor object that is able to keep the resources needed for the offline mode.
cache.addAll(urls)
Adds all the resources specified with the URLs to the named cache for the future, possibly offline, use.

Within the Service Worker instance - Requests cache

function isSuccessful(response) {
  return response &&
    response.status === 200 &&
    response.type === 'basic';
}

self.addEventListener('fetch', function (event) {
  event.respondWith(
    caches.match(event.request)
      .then(function (response) {
        if (response) {
          return response; // Cache hit
        }

        return fetch(event.request.clone())
          .then(function (response) {
            if (!isSuccessful(response)) {
              return response;
            }

            caches.open(CACHE_NAME)
              .then(function (cache) {
                cache.put(event.request, response.clone());
              });

            return response;
          }
        );
      })
    );
});
self.addEventListener('fetch', listener)
An event fired within the Service Worker whenever any of its related browser tabs have issued a HTTP request. Useful to serve already cached response or intercept and cache the incoming response.
event.respondWith(promise)
A fetch event method that expects a Promise which resolves with the request data to be returned to the requesting browser tab.
cache.put(request, response)
Adds the specified response for the request to the named cache for the future, possibly offline, use.
caches.match(event.request)
Returns a Promise resolved when the fetch event represents a request to the resource already cached within the Service Worker's cache.

See also this website's own Service Worker implementation.

Content Indexing API (Google Chrome experimentation)

serviceWorkerRegistration.index.add({id, url, title, description, icons, category})
Adds an entry identified by id to the offline index, with its metadata. It does not cache the entry – it needs to be separately added using Cache API.
serviceWorkerRegistration.index.delete(id)
Removes the previously added entry identified by id from the offline index.
serviceWorkerRegistration.index.getAll()
Returns a Promise resolved with the list of entries previously added to the index.
self.addEventListener('contentdelete', listener)
An event fired within the Service Worker when the entry from the index has been deleted by the user. Useful for removing the resources from the Cache API.

Resources

Get in touch