Skip to content

Commit 55bf338

Browse files
authored
Simplify the refresh banner example.
Use a prolyfill of `navigator.serviceWorker.waiting` and `ServiceWorker.skipWaiting()` to simply implementation. Fixes google#5504
1 parent 819eaaf commit 55bf338

File tree

1 file changed

+39
-72
lines changed

1 file changed

+39
-72
lines changed

src/content/en/tools/workbox/guides/advanced-recipes.md

Lines changed: 39 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,34 @@ description: Advanced recipes to use with Workbox.
1515
A common UX pattern for progressive web apps is to show a banner when a service
1616
worker has updated and waiting to install.
1717

18-
To do this you'll need to add some code to your page and to your service worker.
18+
To do this you'll need to add some polyfill code to your page and to your service worker.
1919

2020
**Add to your page**
2121

2222
```javascript
23+
// polyfill navigator.serviceWorker.waiting
24+
if (!('waiting' in navigator.serviceWorker)) {
25+
navigator.serviceWorker.waiting = new Promise(function(resolve) {
26+
navigator.serviceWorker.ready.then(function(reg) {
27+
function awaitStateChange() {
28+
reg.installing.addEventListener('statechange', function() {
29+
if (this.state === 'installed') resolve(reg);
30+
});
31+
}
32+
if (reg.waiting) resolve(reg);
33+
if (reg.installing) awaitStateChange();
34+
reg.addEventListener('updatefound', awaitStateChange);
35+
})
36+
});
37+
}
38+
39+
// polyfill ServiceWorker.skipWaiting()
40+
if (!('skipWaiting' in ServiceWorker.prototype)) {
41+
ServiceWorker.prototype.skipWaiting = function() {
42+
this.postMessage('skipWaiting');
43+
}
44+
}
45+
2346
function showRefreshUI(registration) {
2447
// TODO: Display a toast or refresh UI.
2548

@@ -40,79 +63,27 @@ function showRefreshUI(registration) {
4063

4164
button.disabled = true;
4265

43-
registration.waiting.postMessage('force-activate');
66+
registration.waiting.skipWaiting();
4467
});
4568

4669
document.body.appendChild(button);
4770
};
4871

49-
function onNewServiceWorker(registration, callback) {
50-
if (registration.waiting) {
51-
// SW is waiting to activate. Can occur if multiple clients open and
52-
// one of the clients is refreshed.
53-
return callback();
54-
}
55-
56-
function listenInstalledStateChange() {
57-
registration.installing.addEventListener('statechange', function() {
58-
if (event.target.state === 'installed') {
59-
// A new service worker is available, inform the user
60-
callback();
61-
}
62-
});
63-
};
64-
65-
if (registration.installing) {
66-
return listenInstalledStateChange();
67-
}
68-
69-
// We are currently controlled so a new SW may be found...
70-
// Add a listener in case a new SW is found,
71-
registration.addEventListener('updatefound', listenInstalledStateChange);
72-
}
73-
74-
window.addEventListener('load', function() {
75-
// When the user asks to refresh the UI, we'll need to reload the window
76-
navigator.serviceWorker.addEventListener('message', function(event) {
77-
if (!event.data) {
78-
return;
79-
}
80-
81-
switch (event.data) {
82-
case 'reload-window':
83-
window.location.reload();
84-
break;
85-
default:
86-
// NOOP
87-
break;
88-
}
89-
});
90-
91-
navigator.serviceWorker.register('/sw.js')
92-
.then(function (registration) {
93-
// Track updates to the Service Worker.
94-
if (!navigator.serviceWorker.controller) {
95-
// The window client isn't currently controlled so it's a new service
96-
// worker that will activate immediately
97-
return;
98-
}
99-
100-
onNewServiceWorker(registration, function() {
101-
showRefreshUI(registration);
102-
});
103-
});
72+
navigator.serviceWorker.addEventListener('controllerchange', function() {
73+
window.location.reload();
10474
});
75+
76+
navigator.serviceWorker.waiting.then(showRefreshUI);
10577
```
10678

107-
This code handles the verious possible lifecycles of the service worker
79+
The polyfill handles the verious possible lifecycles of the service worker
10880
and detects when a new service worker has become installed and is waiting to
10981
activate.
11082

111-
When a waiting service worker is found we set up a message listener on
112-
`navigator.serviceWorker` so we know when to reload the window. When the
113-
user clicks on the UI to refresh the page, we post a message to the new
114-
service worker telling it to force an activation. After this a message is
115-
posted to all windows telling them to reload.
83+
When a waiting service worker is found we we tell the service worker to skip
84+
waiting (posting a message if necessary). After this, the `controllerchange`
85+
event will fire. The page should reload when the controller changes to
86+
ensure that all tabs are running the same version of the code.
11687

11788
Note: This is one possible approach to refreshing the page on a new service
11889
worker. For a more thorough answer as well as an explanation of alternative
@@ -122,19 +93,18 @@ discuess a range of options.
12293

12394
**Add to your service worker**
12495

96+
This code supports the polyfill while we wait for `ServiceWorker.skipWaiting`
97+
to be available in all browsers.
98+
12599
```javascript
126100
self.addEventListener('message', (event) => {
127101
if (!event.data){
128102
return;
129103
}
130104

131105
switch (event.data) {
132-
case 'force-activate':
106+
case 'skipWaiting':
133107
self.skipWaiting();
134-
self.clients.claim();
135-
self.clients.matchAll().then((clients) => {
136-
clients.forEach((client) => client.postMessage('reload-window'));
137-
});
138108
break;
139109
default:
140110
// NOOP
@@ -143,10 +113,7 @@ self.addEventListener('message', (event) => {
143113
});
144114
```
145115

146-
This will receive a the 'force-activate' message and call `skipWaiting()` and
147-
`clients.claim()` so that the service worker activates immediately and controls
148-
all of the currently open windows. We then message each window with a
149-
'reload-window' message so each tab is refreshed with the latest content.
116+
This will receive a 'skipWaiting' message and call `skipWaiting()`.
150117

151118
## "Warm" the runtime cache
152119

0 commit comments

Comments
 (0)