One of the less visible features we have rolled out as part of our brand new Red Badger website is service workers support. If you navigate to our homepage using Chrome, Firefox or Opera, you can turn on the dev tools and see the currently active service worker associated with our domain.
Once you’ve visited one of the pages of the new site, all subsequent pages and assets will be cached in the browser. Now this is where things become interesting. From this moment we have full control over the site behaviour depending on the network and cache availability.
Two direct benefits are:
- Faster asset serving from the browser cache
- Site availability when there is no network
None of that will work by default. It all depends on your service workers implementation.
What we do
While the network is available we’re completely ignoring the caching aspect of the service workers. It becomes completely transparent and all requests are simply passed through. All responses are however cached in the browser.
But here’s the important part. Once the fetch requests start to fail, we will try and respond with cached objects.
This means there is no more dinosaur page. From now on we’re responsible for the offline experience of a user visiting our site.
There are 2 basic scenarios you need to consider in order to handle offline mode:
1. The user navigates to a cached page. This is when we can safely serve cached content and satisfy the user.
2. The user navigates to a page that is not available in the cache. By default, you would be presented with some sort of connection error page. With service workers, we take over that behaviour and serve a different page, which is a part of our site. The user will find a familiar looking header, footer, as well as a friendly message and one of our blogs on service workers.
The best part is that once cached the site will be available even if you close the browser window and open it again.
Try it today
Open our homepage. Disable your internet connectivity. Reload the page. Try navigating around.
If you’re into Chrome developer tools, there is a neat trick that can emulate offline mode specifically for a given tab. Go to Application -> Service Workers and enable the Offline checkbox. Now reload the page.
During the transition period, we’ve encountered an interesting issue. Our old blog was hosted on Wordpress, which hardcodes URL:s for the attachments in posts. All image tags would contain absolute URL:s with http:// in them. This is when we were reminded that service workers are indeed https only.
Once the service worker has been installed, it will continue caching everything on that domain. At that time, we had 4 different apps responsible for serving content, depending on the part of the site you were hitting. This doesn’t really concern the service worker. Once it is installed, it takes charge of the whole domain.
We ended up temporarily disabling service workers for the whole site, migrating the blog to a different platform, and then re-enabling the service workers.
It makes total sense to be HTTPS only. From service workers perspective there are also security concerns. You want to be 100% sure the traffic you’re receiving is the original and intended traffic. HTTPS makes it very hard to alter the traffic.
There is no fallback in the case of the browser not supporting service workers. This feature is advertised as an optional progressive enhancement. At the moment of writing, there is zero support on IE/Edge, Safari and, most importantly, iOS Safari.
On the other hand, there is full support for Android Chrome, desktop Chrome, Firefox and Opera. According to jakearchibald.github.io/isserviceworkerready/Microsoft is implementing the support for Edge as we speak, and Apple is considering it for Safari.
There are a few important concepts around the way service workers function in the browser. Certain aspects of it could cause undesirable behaviour for end users.
Assets of our new website are cache busted. This means that once an asset changes, there is a new hash generated and appended to the asset filename. As a consequence, service workers by default will cache all versions of the asset. This can present an issue on mobile devices with limited disk space.
A responsible way to approach this would be to increment global cache version of the service worker. This way we would invalidate the old cache every time a new version of the site is deployed.
One thing to consider is to be more specific in terms of what we want to cache. Currently, we are caching everything, but if we’re concerned about potentially large assets being cached, we could specify a list of routes that should be cached and the rest would be ignored.
Updating a service worker
When the browser loads a page it will check for a newer version of the service worker. If it exists, it will be installed and put into the queue. In order to activate a new version of the worker, you will have to close all tabs that are currently using that Worker and open the site in a new tab.
There is a way to force update service worker, but there are no good reasons for us to enforce such behaviour.
Our super simple service worker implementation for the new Red Badger site can be found here: https://github.com/redbadger/website-honestly/blob/master/site/sw.js
Highly inspiring talk by Jake Archibald on Instant Loading: Building offline-first Progressive Web Apps - Google I/O 2016
Title image by @MonikaKoziol