Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent Service Worker from automatically stopping

Service Worker seems to automatically stop at some point. This behaviour unintentionally closes the WebSocket connection established on activate.

When and Why does it stop? How can I programmatically disable this unexpected action to keep Service Worker stay running?

like image 254
Lewis Avatar asked Apr 20 '15 07:04

Lewis


People also ask

Why do service workers go inactive?

Service worker (SW) can't be persistent by definition and the browser must forcibly terminate all of SW connections such as network requests or runtime ports after a certain time, which in Chrome is 5 minutes. The inactivity timer when no such requests or ports are open is even shorter: 30 seconds.

Can service worker work when browser is closed?

Their main role is to handle events fired by the browser, or your webpage, and intercept network requests. You can think of it as a gatekeeper for your network requests. Service workers have a total control over every request made from a website. Since they run in the background, they don't need the webpage to be open.

How long does a service worker last?

Chrome terminates a SW if the SW has been idle for 30 seconds. Chrome also detects long-running workers and terminates them. It does this if an event takes more than 5 minutes to settle, or if the worker is busy running synchronous JavaScript and does not respond to a ping within 30 seconds.

How do I disable service worker?

Go to Developer Tools (ctrl shift i/cmd opt i) or right-click on any page element, then click Inspect. Go to the Application tab and then click on service workers in the left bar. It will list all the registered service workers. Click on unregister to disable that particular service worker.


2 Answers

What you're seeing is the expected behavior, and it's not likely to change.

Service workers intentionally have very short lifespans. They are "born" in response to a specific event (install, activate, message, fetch, push, etc.), perform their task, and then "die" shortly thereafter. The lifespan is normally long enough that multiple events might be handled (i.e. an install might be followed by an activate followed by a fetch) before the worker dies, but it will die eventually. This is why it's very important not to rely on any global state in your scripts, and to bootstrap any state information you need via IndexedDB or the Cache Storage API when your service worker starts up.

Service workers are effectively background processes that get installed whenever you visit certain web pages. If those background processes were allowed to run indefinitely, there's an increased risk of negative impact on battery and performance of your device/computer. To mitigate this risk, your browser will only run those processes when it knows it's necessary, i.e. in response to an event.

A use case for WebSockets is having your client listen for some data from the server. For that use case, the service worker-friendly alternative to using WebSockets is to use the Push Messaging API and have your service worker respond to push events. Note that in the current Chrome implementation, you must show a user-visible notification when handling a push event. The "silent" push use case is not supported right now.

If instead of listening to data from the server, you were using WebSockets as a way of sending data from your client to your server, there's unfortunately no great service worker-friendly way of doing that. At some point in the future, there may be a way of registering your service worker to be woken up via a periodic/time-based event at which point your could use fetch() to send data to the server, but that's currently not supported in any browsers.

P.S.: Chrome (normally) won't kill a service worker while you have its DevTools interface open, but this is only to ease debugging and is not behavior you should rely on for a real application.

like image 200
Jeff Posnick Avatar answered Sep 27 '22 18:09

Jeff Posnick


The Theory

Jeff's answer explains the theory part - why and how, in detail.

It also includes many good points on why you might not want to pursue this.

However, in my case, the downsides are nonexistent since my app will run on desktop machines which are reserved only to run my app. But I needed to keep the SW alive even when the browser window is minimized. So, if you are working on a web app which will run on variety of devices, keeping the SW alive might not be a good idea, for the things discussed in above answer.

With that said, let's move onto the actual, practical answer.

My "Practical" Solution

There should be many ways to keep the SW alive, since SWs stay alive a bit after responding to many different events. In my case, I've put a dummy file to server, cached it in the SW, and requested that file periodically from the document.

Therefore the steps are;

  • create a dummy file on the server, say ping.txt
  • cache the file on your SW
  • request that file from your html periodically to keep the SW alive

Example

// in index.html setInterval(function(){     fetch('/ping.txt') }, 20000) 

The request will not actually hit the server, since it will be cached on the SW. Nonetheless, that will keep the SW alive, since it will respond to the fetch even evoked by the request.

PS: I've found 20 seconds to be a good interval to keep the SW alive, but it might change for you, you should experiment and see.

like image 25
Umur Karagöz Avatar answered Sep 27 '22 19:09

Umur Karagöz