Msw: Chrome removes idle service worker after 30-40 seconds

Created on 1 Sep 2020  路  3Comments  路  Source: mswjs/msw

Describe the bug

Because of the way user agents handle idle service worker (https://www.w3.org/TR/service-workers-1/#service-worker-lifetime) they can, and will, be disabled after a certain time has passed.

This is usually not an issue. However, we have an e2e-test that is running for +40 seconds, filling out a form in various ways, before making the request. During this time the service worker will have been disabled by the user agent. The request that should be intercepted will instead fall through and in this case, fail.

Basically. If the msw is idle long enough it will be disabled until the page is reloaded. If the first request to the msw is made after +40 seconds of other application interactions it will not be enabled once the request is made.

Environment

See codesandbox package.json for details

  • msw: 0.20.5
  • chrome: 84

To Reproduce

Steps to reproduce the behavior:

  1. Go to https://codesandbox.io/s/hidden-currying-u0ec0?file=/src/App.tsx
  2. When the app has loaded it's possible to make a fetch by pressing the button, this will get intercepted by MSW.
  3. Reload the codesandbox preview browser and wait about 42 seconds (From my experiments I've found that having devtools open will prevent the service worker from timing out. It have to be closed to reproduce the error)
  4. Press the fetch button
  5. Notice the error message getting rendered. This message is the error from trying to JSON-parse the html that is returned by the SPA as the request to the /test-endpoint is not intercepted by the msw any longer.

Expected behavior

It does not seem to be possible to prevent the user-agent from disabling the service worker if it's idle for too long. I see two alternatives:

  1. Keep the msw alive somehow, i.e. constantly make keep-alive requests (not ideal).
  2. Somehow make the msw handle the request even though it was temporarily disabled by the user-agent from not having any events sent to it for too long.
bug potentially solved browser

Most helpful comment

Alright, a little update here - I tested this ping/pong theory. It's safely kept the worker running for about an hour while in a background tab. I'll open a PR with the basic implementation for review.

Regarding the state events, that's a non-starter as there is no state change event for when it's stopped.

All 3 comments

This is what I've been experiencing and I didn't even realize. Thanks for providing some explanation I now understand why this keeps happening while I've developing against mock endpoints. I'm finding that this happens sooner in Firefox than in Chrome. I will test this some more.

This is going to be a random timeout in every browser environment and machine _(some specs say 30s, but I haven't be a hard rule yet)_. For example, it takes roughly 2 minutes for the above CSB to cause that behavior to happen for me. I was reading up on this the other day and it's a surprisingly challenging problem. Browsers are very aggressive about terminating idle workers as they're meant to be short-lived.

Per @slowselfip 's suggestions, we may be able to just ping/pong with the service worker as it treats a message the same as a fetch event as long as it doesn't appear to be illegitimate behavior _(two service workers doing this to stay alive would be terminated)_. I thought we could also tie into a state change event on the worker to restart it, but it appears to not emit anything when it's terminated by the user agent.

Alright, a little update here - I tested this ping/pong theory. It's safely kept the worker running for about an hour while in a background tab. I'll open a PR with the basic implementation for review.

Regarding the state events, that's a non-starter as there is no state change event for when it's stopped.

Was this page helpful?
0 / 5 - 0 ratings