-
Notifications
You must be signed in to change notification settings - Fork 821
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Document the event handler created by workbox-core's clientsClaim() #2070
Comments
"activated" represents the state of a given service worker. In practice, it effectively means that the service worker has completed whatever initial setup and cleanup steps that were configured in the "controlling" represents the relationship between an activated service worker and a given client, like the So it's possible for a service worker to be "activated" (meaning that it could theoretically handle Whether or not your newly activated service worker takes control of an existing window client depends on whether you're using This is explained in more detail at https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle#clientsclaim Hopefully that clears things up! I'm going to close this issue, but let me know if there is still confusion and we can revisit. |
@jeffposnick Thanks for the feedback -- that definitely makes sense in theory, and I get that listening to Feeling a bit stupid now and I'm still not really sure what was f*** up, but I just had to restart Chrome and afterwards the Thanks again! |
@jeffposnick I face the same issue as faced by @qqilihq , in my case i am call periodically workbox update method to check for update, but in my case new service get activated but controlling event never gets fired. Is there somethinng i am missing please guide me. Thanks in Advance! |
@hannandesai, if you could provide details about which version of |
@jeffposnick We are having very similar problems as hannandesai. We are using interface WorkboxWorkerAction {
type: keyof typeof serviceWorkerActions;
}
// Ensure to keep `createMockWorker` in sync with this when making changes
interface WorkboxWorker {
register(): Promise<ServiceWorkerRegistration | undefined>;
checkUpdate(): void;
skipWaiting(): void;
sendMessage(action: WorkboxWorkerAction): Promise<void>;
}
export default function createWorkboxWorker(): WorkboxWorker {
const wb = new Workbox(path.join([__PUBLIC_PATH__, 'sw.js']));
let isUncontrolled = true;
wb.addEventListener('controlling', () => {
window.location.reload();
});
wb.addEventListener('waiting', () => {
adapters.resolve('appStore').dispatch(
updateAvailable({
isUpdateAvailable: true,
})
);
});
return {
register() {
return new Promise((resolve, reject) => {
wb.register().then((registration) => {
// After a "Hard Refresh" browsers will not attach the window to a
// previously active Service Worker. When this happens we mark the
// worker registration as uncontrolled and clear the media providers
// so that when the user loads the app normally the next time they get
// an up to date plex.tv/media/providers that isn't loaded from cache.
// A strict `null` check here is intentional, since `controller` will
// specifically have a `null` value, where if `serviceWorker` is not
// supported or disabled it will return `undefined`.
// See: https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle#shift-reload
isUncontrolled = window.navigator?.serviceWorker.controller === null;
if (registration?.active && isUncontrolled) {
log(
'[Workers] Service Worker registered but is uncontrolled, possibly due to a hard refresh'
);
messageSW(registration.active, {
type: serviceWorkerActions.CLEAR_CLOUD_MEDIA_PROVIDERS,
});
}
resolve(registration);
}, reject);
});
},
checkUpdate() {
log('[Workers] Checking for updates');
wb.update();
},
skipWaiting() {
log('[Workers] Installing new service worker');
wb.messageSkipWaiting();
},
sendMessage(action: WorkboxWorkerAction) {
return new Promise<void>((resolve, reject) => {
// When the page does not claim the service worker wb.sendMessage will
// never resolve nor reject. When we know we are in this state force a
// rejection in the promise
if (isUncontrolled) {
reject();
} else {
wb.messageSW(action).then((response) => {
if (response === serviceWorkerActions.DONE) {
resolve();
} else {
reject();
}
});
}
});
},
};
} In our self.addEventListener('message', (event) => {
if (!event || !event.data) {
return;
}
switch (event.data.type) {
case serviceWorkerActions.SIGN_OUT:
case serviceWorkerActions.CLEAR_CLOUD_MEDIA_PROVIDERS:
mediaProvidersCachePlugin.deleteCacheAndMetadata().then(
() => {
event.ports[0].postMessage(serviceWorkerActions.DONE);
},
() => {
event.ports[0].postMessage(serviceWorkerActions.FAIL);
}
);
break;
case serviceWorkerActions.SKIP_WAITING:
self.skipWaiting();
core.clientsClaim();
break;
}
}); We have code that creates a singleton from We then have a component that calls After calling If a user manually reloads the page, the service worker is installed as expected. If a user loads the app and an update is available, the modal displays as expected and pressing "Update" correctly fires the I have read though https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration/update along with the workbox documentation, but have not been able to figure out this issue. It is unclear if we're holding Thank you for any guidance and time you can provide to help with this problem! |
@jeffposnick Thanks for the reply. Below is my code for service worker registration using workbox-window
Below is my service worker file
Here i check for uodates manually after every one minute. |
controlling
vs. activated
event
Hello @chrishoage and @hannandesai! Thanks for sharing that. I'll provide specific debugging feedback on each implementation. Before I do that, I just wanted to clarify what Prior to Workbox v6, This behavior—registering and event handler which called the underlying method in response to the relevant event—ended up confusing a number of developers, and we didn't do a good job of explaining it in our documentation. Specifically, developers who called In the case of the workbox/packages/workbox-core/src/skipWaiting.ts Lines 23 to 33 in 27080cc
The workbox/packages/workbox-core/src/clientsClaim.ts Lines 21 to 23 in 27080cc
(Again, apologies that this nuance is currently unclear from reading the docs.) This is all to say that if you're using Long-term, maybe we should remove the |
@jeffposnick Thank you for the detailed write up. In our case, we only added We noticed there were a few places in the docs that You can safely ignore that line in my example above, because the behavior we are experiencing happens with or with out it. |
@jeffposnick Thanks you for detailed explanation this help me understands clientsClaim() wrapper clearly. But as i mentioned i tried clientsClaim() wrapper at top level also but still it wont trigger the controlling event, and just to inform controlling event is called when i manually reload the page but when we try to update service worker using workbox update method it wont get called. |
Yup, understood. I will dive into both code samples soon. I just know that |
@hannandesai: Just a few random comments: I had some issues getting your code to compile as-is, because you're doing things like But in any case, I see some problems with the following code:
In this case, A In the course of exploring this issue, though, I realized that the So, once #2768 is resolved, you should be able to write:
In the meantime, instead of using
The rest of the general logic could remain the same in that case. |
@jeffposnick yup, sorry as i forgot to correct the code, that listening controlling event for serviceWorker.wating is just to give it a try, otherwise i am using as you mentioned. Will definitely looking forward for #2786 to resolve. Thanks in Advance |
@hannandesai, just to reiterate, if you need this functionality you don't have to wait for #2786. You can add
to your code right now if you want to be notified of the controller changing all the time. If you only want to be notified when the controller changed after being previously being set to a different service worker, add the event listener conditionally:
That should be functionally identical to what the |
@chrishoage, looking at your
won't currently fire if the service worker that takes control was installed and activated due to a The same workaround mentioned above should apply, where you listen to the |
@jeffposnick Thank you for your help in diagnosing the problem. Good to know we were not holding it wrong. We will wait for the PR linked in the GHI to land. |
(The documentation changes, which this issue tracks, have already landed.) |
Library Affected:
workbox-sw, workbox-window
Browser & Platform:
all browsers
Issue or Feature Request Description:
I'm following the “Offer a page reload for users” from “Advanced Recipes”. The sample code suggest to listen to the WB
controlling
event and then perform the reload. This event is never triggered for me.When I change it to
activated
it works.Is this an error in the docs or am I doing something wrong?
When reporting bugs, please include relevant JavaScript Console logs and links to public URLs at which the issue could be reproduced.
service-worker.js
:service-worker-registration.js
:The text was updated successfully, but these errors were encountered: