Adding a service worker

Next, you need to register a service worker. This is done in what I call the client-side code, which is the JavaScript you are accustomed to writing. Service workers execute in a separate thread from the UI. I think about it as a background process. You still need to register the service worker for the site.

For simple registrations, like this example, my preferred method is a script block at the bottom of my site's markup. First, detect if service workers are supported. If they are, then attempt to register the site's service work. If the browser does not support service workers, skip the registration code so no exceptions occur.

Registration is done by calling the navigator.serviceWorker.register function. It accepts a single argument, which is a path to the service worker file. I will review more rules around this in later chapters.

The register function returns a promise. You can add code to log successful registration as follows:

      <script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js').then(function
(registration) { // Registration was successful
console.log('ServiceWorker registration successful with
scope: ', registration.scope);
}).catch(function (err) { // registration failed :(
console.log('ServiceWorker registration failed: ',
err);
});
}
</script>

We will start diving into details about service workers in Chapter 5, The Service Worker Life Cycle. To help you understand the example code, let me introduce some service worker fundamentals. Service workers are completely asynchronous. They enter an idle or sleep state if they are not needed. They wake up or spin up completely in response to the operating system or browser firing and events.

All logic execution is a product of events. You must register event handlers to execute your service worker logic. The 2048 service worker registers event handlers for the install, activate, and fetch events.

The 2048 game service worker pre-caches the entire application in the install event. You will learn more about caching strategies in Chapter 6, Master the Cache API – Manage Web Assets in a Podcast Application. For now, we will cache the application so it is available all the time, without any network chatter:

self.addEventListener("install", function (event) {
console.log("Installing the service worker!");
caches.open("PRECACHE")
.then(function (cache) {
cache.addAll(cacheList);
});
});

The 2048 service worker caches assets in the install event. The application assets are defined in an array in the server worker code. The cache API provides an interface to a special storage designed specifically to persist response objects. I will defer the details to later chapters:

var cacheList = [
"index.html",
"style/main.css",
"js/keyboard_input_manager.js",
"js/html_actuator.js",
"js/grid.js",
"js/tile.js",
"js/local_storage_manager.js",
"js/game_manager.js",
"js/application.js"
];

The service worker also has an activate and a fetch event handler. A fetch event handler must be registered before the add to homescreen feature can be triggered.

The fetch event fires when the browser requests an asset from the network. This could be an image, stylesheet, script, AJAX call, and so on. The event parameter contains the request object and can be used to check your cache to see if the asset is available:

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

Without a fetch event handler, your application cannot work offline. There is no requirement that the handler catch any requests, just that it is registered. It is a minimal check for offline capability.

In the example fetch event handler, all caches are interrogated to see if there is an existing match to the request. If so, the locally cached version is returned. If not, the request is passed to the network.

That's it; congratulations! Your website is now a PWA, at least on your local machine:

At this point, loading the 2048 localhost site in Chrome should cause an add to homescreen prompt being displayed. If not, reload the page once or twice and apply focus to the browser tab. If you are still not seeing the prompt, check the console for any error messages and debug them accordingly.