Rethinking Offline First sync for Service Workers
On the surface, Service Workers look quite similar to Web Workers. They both run on separate threads from the main UI thread, they have a global
self
object, and they tend to support the same APIs. However, while Web Workers offer a large degree of control over their lifecycle (you can create and terminate them at will) and are able to execute long-running JavaScript tasks (in fact, they’re designed for this), Service Workers explicitly don’t allow either of these things. In fact, a Service Worker is best thought of as “fire-and-forget” — it responds to events in an ephemeral way, and the browser is free to terminate any Service Worker that takes too long to fulfill a request or makes too much use of shared resources.This led us to our first real hurdle with Service Worker. Our goal, as we originally conceived it, was to use PouchDB’s existing replication APIs to enable bi-directional sync between the client and the server, with the client code isolated entirely to the Service Worker.
[…]
This resulted in a silent error, which took quite a while to debug. The culprit? Well, PouchDB’s “live” sync depends on HTTP longpolling — in other words, it maintains an ongoing HTTP connection with the CouchDB server, which is used to send real-time updates from the server to the client. As it turns out, this is a big no-no in Service Worker Land, and the browser will unceremoniously drop your Service Worker if it tries to maintain any ongoing HTTP connections. The same applies to Web Sockets, Server-Sent Events, WebRTC, and any other network APIs where you may be tempted to keep a constant connection with your server.
What we realized is that “the Zen of Service Worker” is all about embracing events. The Service Worker receives events, it responds to events, and it (ideally) does so in a timely manner — if not, the browser may preemptively terminate it. And this is actually a good design decision in the spec, since it prevents malicious websites from installing rogue Service Workers that abuse the user’s battery, memory, or CPU.