Going Offline: Designing An Ideal Offline Experience With Service Workers By Jeremy Keith
Books in the "A Book Apart" series are just a pleasure to read. They are often the perfect length with just the right amount of content. They cover complex ideas; but, always make sure to cater to readers who are newer in the industry. They feel informal; but very professional. Going Offline: Designing an Ideal Offline Experience with Service Workers by Jeremy Keith is no exception. This book gently walks the reader through the concepts and application of Service Workers - a topic that feels a lot more abstract and etherial than much of the JavaScript code I'm used to creating. And, as someone who has no experience with the topic, I came away from the book feeling excited to dig in and get started.
|
|
|
||
|
|
|||
|
|
|
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)
As someone who has no Service Worker experience but, does who does have a lot of JavaScript experience, this left me feeling uncomfortable. After all, the normal web page life-cycle doesn't typically deal with any "powering down" concern (less the unload / beforeunload events). And certainly, in Node.js, any running or queued task will hold the process open. So, hearing that Service Workers may power down mid-execution felt somewhat unbelievable.
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.
If you're interested in the "offline first" movement or want to learn more about Service Workers, Going Offline by Jeremy Keith is a really gentle and highly accessible introduction to the topic. At times, it even felt "too gentle", with Keith taking a moment here and there to explain what a "variable" is and what "JSON" (JavaScript Object Notation) is. But, this just goes to show you the unassuming and welcoming mindset behind writing a book like this one. Definitely a recommended read for people who want a primer on how Service Workers can help you build a better user experience (UX).
Reader Comments
Sounds great. I've played with SWs before and found it to be a powerful API. Don't think I ever came across waitUntil(). Glad you called that out.
FYI: typo "but, does who does have"
@Chris,
What kinds of stuff have you used Service Workers for? Has it been more "App" kind of things? Or, have you used this more for "Website" kind of things (if the differentiation there makes sense).
I'm excited to get my toes wet.
@ Ben
In my case, we had an online-first back-office app that needed to work offline. It was used to adjust inventory levels and assumed (inaccurately) that our clients would always have access to wifi. So I started experimenting with service workers to solve the offline problem, caching inventory updates locally to submit to our ColdFusion backend once reconnected. I got it working in the context I was testing, but didn't have the resources to test the entire app, so we unfortunately lacked the confidence needed to launch. And they moved me onto other things before I could truly finish it up.
@Chris,
That actually sounds really cool! A while back, I played around with PouchDB, because of its ability to sync with a live database. But, in the case that I was looking at, each user would have their own live database to sync to. I am not sure that such a technology would even make sense when multiple people need to sync to a single database (not even sure how that would work). So, that's pretty cool that you essentially buffered API calls (or however it was done). Sounds exciting! Sorry you didn't get a chance to finish it.