29

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?

Lewis
  • 14,132
  • 12
  • 66
  • 87
  • Out of curiousity, why aren't you using SharedWorkers for this? – JaffaTheCake Apr 20 '15 at 17:04
  • 2
    @JaffaTheCake Just because ServiceWorker is complex enough for my small offline app. I used to implement the SharedWorker + Appcache approach but I switched to ServiceWorker because of the *longer lifespan* stuff. In addition, SharedWorker has [a bug](http://stackoverflow.com/questions/28913545/shared-worker-is-teminated-on-reloading-page) on reloading page. – Lewis Apr 21 '15 at 03:39

3 Answers3

51

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.

Jeff Posnick
  • 53,580
  • 14
  • 141
  • 167
  • 5
    It's a really really bad news to me. From your point, in comparison with SharedWorker, ServiceWorker actually just has **a longer existence, but a temporary lifespan** instead of a longer lifespan. IMHO, it should be alive at least untill all dependent pages are closed (like SharedWorker). I used to love ServiceWorker, but my heart is now completely broken because of this. – Lewis Apr 21 '15 at 03:57
  • 7
    ServiceWorker is for handling events that need to fire outside of the context of a page. It isn't for background processing, that's what SharedWorker is for. If you try to use it for processing, it's likely to block fetch events which is terrible for performance. We're hoping to enable SharedWorkers *inside* ServiceWorkers, since they're for different things. – JaffaTheCake May 19 '15 at 16:57
  • 4
    I thought PWA where here to defeat native apps, currently the things that are holding us back is: Long running background task, raw tcp & udp things we can never have in the web I would rather want to have some permission api for allowing long running sw or see that browser informs about workers that performs negative. There is good intentions too with long running service worker. a simple prompt with "example.com is still running background processing... `[destroy]` `[keep alive]` `[ ]` don't ask again" would make me happy – Endless Apr 25 '19 at 19:08
  • 2
    @JaffaTheCake ...which means I shouldn’t use service workers to share a WebSocket connection with multiple pages and keep it alive. Thanks for your words. – Константин Ван Dec 16 '19 at 12:46
  • 3
    Almost 6 years later of _"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 […]"_ Any plans yet for this apparently much desired feature? – Serge Stroobandt Apr 07 '21 at 15:28
  • Hey this is so relevant to what i want.. i am using socket inside web worker and getting periodic updates when required.. however worker destroys at it times and then i dont get updates... is there any way to handle it now to get updates perodicly and the worker keeps alive ??? – Murtaza Hussain Apr 15 '21 at 07:57
  • Forgive me if i'm asking a very basic question but sending message to the serviceworker doesn't seem to wake up the serviceworker. What could be the reason? – John Yepthomi Nov 02 '21 at 18:46
  • Anybody knows if it's possible to handle web push events when the service worker is in `activated and is stopped` state? – rockdaswift Jul 21 '22 at 11:49
6

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.

Umur Karagöz
  • 2,970
  • 1
  • 19
  • 29
0

I think the current implementation is as it should be. I don't want 100's of apps running in the background on my phone. I expect that when I am in the app some process will be running.

Umur's idea of using ping.txt to keep it alive will accomplish keeping it alive but it begs the question why not have that code run in the browser context?

Service workers solve an important problem and make offline experiences a reality with a high degree of control. They also provide an excellent mechanism to do push notifications.

Terry Riegel
  • 159
  • 10