Enabling Offline First Experiences on the Web with Service Workers
During the first Offline Camp I had the pleasure to share a weekend with about 30 great people to talk about the Offline First community and movement.
As usual, the technical problem on how to provide users with access to relevant information when connectivity is limited or non-existent is part of a bigger “human” problem with social and economic components. In this article I’m going to focus on a technical aspect—the approach that the web ecosystem takes to the connectivity issue.
How did we get here?
Just save it
Since its beginning, the web has provided a simple solution for storing website information into the user machine to access it later, even in an offline situation. It’s called “Save Page As….” Websites are basically HTML documents, so you can just download them as the browser does for you every time you access a URL. You can even download all the assets the website is accessing.
So, why are we talking today about fancy technologies? There are some reasons why this initial solution is not ideal:
- The user needs to explicitly save the content.
- If the user accesses the same resource again after the content changes, the offline version will be the old one unless the user saves an updated version.
- Single-page applications inject HTML dynamically so this technique won’t work. (Sad but true.)
I don’t want to focus too much on an almost dead web standard, but the Application Cache (AppCache) was included in HTML5 as the first attempt by browser vendors to enable developers to offer an offline experience to their users. The approach that AppCache takes is for developers to define a manifest file describing the necessary files to make offline browsing possible, as well as fallback files for this situation. A natural advantage of this approach is that we as web developers have tools to shape this offline experience.
AppCache proved confusing to web developers and surfaced some important issues. This led the technology to be replaced by the brand new Service Workers specification. Among the difficulties people have found in working with AppCache are:
- Cached files are always retrieved from the filesystem, even if the user is online, making it hard to update them.
- Cached files are only updated if the manifest is updated.
- Non-cached resources won’t load on a “non-cached” page, even if we are offline.
Service Workers offer three features in particular that I think are the most important to provide offline experiences to our users:
- The Cache API gives us access to the creation and management of versioned caches, allowing us to save resources on the user’s file system. This is useful for both offline and online scenarios. If we store a resource in the cache then we can return it from the local file system and prevent an extra round trip request and response to and from the server.
- The Service Worker has access to app lifecycle events. We can take advantage of these events to clean caches, preload and save critical resources. More importantly, we can get a trigger every time a resource is about to be fetched from the web. Inside a Service Worker we have the ability to get the resource from a cache, return a completely new response, or, for example, retrieve the resource from the network and store the result in a Cache before returning it. This is very important for scenarios with limited connectivity since we are in control of the experience every time.
- We as developers are now allowed to ask for Background Syncs. The idea is that we can request that the browser try to sync our local data with the server. If there is no connection or we are on the subway then the browser will try to sync later, when we get a better connection. This is important in particular for local databases and multi-user apps.
Service Workers provide us with powerful tools for shaping amazing experiences for our users, but this can result in low-level APIs. This is why top-level abstractions are necessary for our day-to-day development. Some of the tools that can help us work with Service Workers and offline experiences are:
The website PWA Rocks (which is a PWA itself) compiles a list of really cool Progressive Web Apps. These are some of my favorites:
A note on Lie-Fi
As Jake Archibald explained in his great presentation at Google I/O, offline scenarios are not the only situation we need to look for or have the ability to improve. He defines Lie-Fi as the scenario where our device says we have an internet connection but it’s so slow we should prefer to be offline so we get the “offline experience,” or alternatively, that we have a good connection with a WiFi endpoint but the communication between the WiFi and internet doesn’t work. With the right use of Service Workers we can provide great experiences to all of our users, regardless of their connection status.
If you care about your users and want to see them happily using your app/website in situations in which they never imagined they could use your project, you should start looking around the Service Worker and Progressive Web Apps world.
Editor’s Note: This article is part of series of unconference session recaps submitted by the awesome folks who participated in our first ever Offline Camp, a unique tech retreat that brings together the Offline First community. You can find more coverage of our initial discussions in our Medium publication. To continue the conversation, join us at our next event or sign up for updates and cast your vote on where we should host future editions of Offline Camp.