问题
I'm writing a PWA in Angular that needs to be ready to go offline from a single page load. The documentation for the service worker life cycle specifies that the worker is installed but not active immediately: https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle
This is by design and can be overruled by calling clients.claim()
.
The problem with this is that Angular loads the service worker after the whole app has been loaded so claim()
has nothing left to claim. That means the page has to be reloaded and then all the calls are cached (which works in my case) but that seems like a poor user experience.
I see and have tried the following solutions but have gotten stuck on all of them:
- Listen to the install event on the service worker in
app.component.ts
so that I can wait to do my calls that need to be cached until afterclaim()
has been called. SwUpdate knows nothing about this event (only updates) and while the following could be an option, it's pointless because the service worker has not been loaded sonavigator.serviceworker
is null:navigator.serviceWorker.controller.addEventListener('statechange', (stateChangeEvent: Event) => {})
- Add this to the service worker:
self.addEventListener('install', (event) => {})
but when testing, I need to tick "update on reload" and so each pageload is going to have an install event, meaning I need to have some way to have it happen only once ever to prevent getting in an infinite loop of reloads. I tried doing this with the localstorage but the service worker has no access to that. Apparently it has access to IndexedDB but I still need to learn how that works and this whole "reload the page on first load" strategy doesn't sit right with me - Ensure the service worker js is loaded by Angular before anything else. Of course, the install is async so that would mean race conditions with my app. I haven't been able to find how to influence this load order. I tried placing
ServiceWorkerModule.register('/custom-sw.js')
first inapp.module.ts
but that made no difference.
回答1:
I believe you might be missing the call to skipWaiting()
(link).
skipWaiting()
when called from the install
event will move right on to the activate
event without the user reloading the page.
clients.claim()
in the activate
event will claim any clients available at that time.
If you do not call skipWaiting()
, the activate
event is not fired until next reload of the page.
来源:https://stackoverflow.com/questions/58940683/angular-fully-install-service-worker-before-anything-else