For the last few years, I've been enamored with the idea of "offline first" development. And, I've even spent a good amount of time digging into PouchDB - a client-side database, based on the CouchDB API, that is positioned perfectly for an offline first experience. In my mind, Service Workers were always going to be "the thing" that tied all of my research and development together. But, unfortunately, I never made it that far.
Now, with the light that "Going Offline" has shed on the topic, I'm feeling reinvigorated. But, also, much more educated. Up until reading this book, I had an immature mental model in which "offline first", "Progressive Web Apps (PWAs)", and "Service Workers", were all one in the same. I now see that the use of Service Workers is much more nuanced; and, that it applies to a broader range of projects, not just Single Page Applications (SPAs) and pseudo-native experiences.
In fact, Keith's exploration of an Offline / Fallback page for "normal websites" is probably going to be the first type of Service Worker interaction that I experiment with. I really enjoyed how he used the Fallback page concept to showcase a few facets of this new technology:
- How the Service Worker API can augment - or progressively enhance - a non-"app" context.
- How the Cache API can be used both inside and outside of the Service Worker.
- How other technologies like the LocalStorage API can be used in conjunction with the Cache API in order to provide an even richer user experience.
- How the Cache API can be used to create "Save for Later" functionality.
If I had one criticism of the book, it's that Keith kind of glossed over the .waitUntil() method. As he iterates through his examples, they all grow to include .waitUntil() calls on each Service Worker event object. When this is first encountered, he does explain that the .waitUntil() method is used to hold the event open:
There's a chance that the service worker might "power down" once the user has received the response. If that happens, the copy might never end up in the cache.... you can make sure the copy gets cached by invoking the waitUntil method on the fetchEvent. You're telling the fetchEvent to stay active until the caching code completes, even if a respnose has already been received. (Page 84)
Unfortunately - or perhaps more just "atypically" - this turns out to be the case with Service Workers. When I was done reading the Going Offline book, I went online (see what I did there?) and did a little research on the .waitUntil() method. According to the Service Worker specification, the browser "may" (or, may not) terminate a service worker at any time if:
- It has no event to handle.
- It detects abnormal behavior (such as an infinite loop).
- Its processing time exceeds the imposed time limit.
So, it appears that unlike a Node.js process, "doing work" isn't enough to keep a Service Worker running. As such, you have to use the .waitUntil() method on the Service Worker event objects in order to hold the events open while interacting with the Cache API or the fetch API.
One interesting caveat of this, as pointed out by Chris Love on YouTube, is that a long running "activate" event will actually buffer concurrent fetch events. This is done in order to ensure that the Service Worker is in a consistent state whenever any of the events fire. But, this also means that if your "activate" event takes a while, the user won't be able to make calls for remote resources until the activate event completes.
The .waitUntil() method aside, I felt like Keith went appropriately deep into the other APIs relating to the offline landscape. At no point does the book read like documentation - he never list out all possible methods and arguments. But, he is pragmatic and does explain what all of the methods do in relation to the outcomes he's trying to achieve in the code examples. This keeps the flow of the book feeling very natural and incremental; and, at no point overwhelming.