In part 1 of this series we looked at what Progressive Web Apps are and discussed how they can improve user experiences in mobile web. These articles are based on the talk I gave at the Reversim Summit. If you prefer to watch the video you can see it here:
Let’s continue where we left off last time and dive into Web Workers. Web Workers are the core technologies that enable PWAs.
If you’ve worked a bit with Javascript before you may have noticed that it is single threaded. This is evident if you do any expensive computations on the client side. In these cases the page becomes unresponsive until the script running the computations is finished. A web worker comes to solve the problem of all of our Javascript running on the main thread. A web worker is JS that runs in the background, independently of scripts, without affecting the performance of the page.
A service worker is type of web worker. This means that it is a Javascript file that run separately from the main browser thread. A service worker is event driven and the base for utilising all progressive web application technologies.
First things first. Before listening for service worker events we must register our service worker. This is pretty simple. We just check that the current browser supports service workers, and if it does we register our service worker files.
Now that we’ve registered our service worker we can set up event listeners. The first event fired after registration is the install event.
Lastly, we can listen for the activate event.
We’ve seen how to listen for these lifecycle events. As we dive deeper we’ll take a look at how we can utilise each event for injecting our own custom logic. Let’s put this into action together with our first end to end example.
Let’s implement a simple service worker. We’ll include our service worker file, register and then log the firing of the basic events.
In our main JS file we check whether service workers are supported. If they are let’s register and then log the result of the registration attempt.
Now let’s take a look out our basic service worker loggings.
Finally, we can verify that the service worker events are firing as expected!
Service workers can be used to intercept any network request. We can now watch JS, CSS, HTML and XHR requests! Let’s get familiar with the API. We will simply listen for the fetch event fired by the browser.
The event object supplied as a param to the callback has several properties that enable us to easily detect the origin and method of each outgoing fetch request.
Baby steps first! For every outgoing fetch request let us return static HTML.
We’ll revisit the power of intercepting network requests after we learn about the Cache API.
The Cache API lets us programmatically control the browser cache via a registered service worker. We can store and retrieve network requests and corresponding responses. Imagine the following:
So we can set up dictionaries in our service worker for outgoing requests we are expecting our web app to make. If we have data that should be cached or if we want to reduce network traffic this is exactly the place to do it :) Let’s take a look at some code.
The waitUntil method tells the browser not to kill the service worker until our block of code is done executing. Essentially, we are defining this block of code as critical. Lastly, we write to the browser cache with the put method. This will update an existing key in the cache dictionary or create a new one if it doesn’t exist yet.
The Cache API introduces a bunch of interesting options for programmatically controlling the browser cache. Let’s take a look!
Cache-Only
For every outgoing network request we will try to respond with something from our cache Map. If we don’t have an appropriate response, no luck :/
Network-Only
For every outgoing fetch request we will ignore the cache and forward it to the network. This is exactly what happens when we don’t cache anything at all.
This is less than optimal though! We can do better!
Hybrid Caching Strategies
Let’s take a look at the Cache with Network Backup strategy. For every outgoing fetch request we check to make sure whether or not a response already exists in our Cache Map. If it does we return it. Otherwise we continue to make that fetch requests. This approach is preferred when we have a bias for stale data. For example, for static resources that aren’t updated often.
Now let’s take a look at Network with a Cache Backup. For a given request we try to make a network request. If it fails for any reason we try to supply a response from our cache. This is approach is preferred when we have a bias for fresh data.
Cache API — Handling 404 Images
What is web push?
Web push is the ability to send a push notification to the users browser. This is a big deal! Previously, it was only possible via mobile applications! Web push is supported across all major browsers.
How does web push work?
All major browsers maintain a cloud push service. This means that with the appropriate permissions our servers can make a request to their push service to send a notification our users browser. For a more in depth explanation on this check out the video of the conference talk above. Here will just do the basics.
Obtaining Web Push Permissions
Pretty straightforward!
Subscribe push notification to push manager
All together, from our client.js file (not our service worker) it will look like this:
How to handle a client side push event from browser push service
We simply listen for the push event on the client as follows:
In part 1 and part 2 of this series we’ve seen the power of PWAs. We’ve barely scratched the surface, but I hope you’re walking away with the understanding of how easy and powerful this is.
You can follow me on Instagram, Linkedin , and Medium for more tech related content!