From a6488d643f57fca2fe42ca9a93aeaee93f7390e0 Mon Sep 17 00:00:00 2001 From: Jeffrey Posnick Date: Fri, 12 Oct 2018 09:45:57 -0400 Subject: [PATCH] Updates to clarify the "waiting" SW behavior (#5410) --- template/README.md | 36 +++++++++++++++++++---------------- template/src/serviceWorker.js | 28 +++++++++++++++------------ 2 files changed, 36 insertions(+), 28 deletions(-) diff --git a/template/README.md b/template/README.md index c591bbf0d00..60acc10653b 100644 --- a/template/README.md +++ b/template/README.md @@ -1896,16 +1896,32 @@ or unreliable network. If you do decide to opt-in to service worker registration, please take the following into account: +1. After the initial caching is done, the [service worker lifecycle](https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle) +controls when updated content ends up being shown to users. In order to guard against +[race conditions with lazy-loaded content](https://github.com/facebook/create-react-app/issues/3613#issuecomment-353467430), +the default behavior is to conservatively keep the updated service worker in the "[waiting](https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle#waiting)" +state. This means that users will end up seeing older content until they close (reloading is not +enough) their existing, open tabs. See [this blog post](https://jeffy.info/2018/10/10/sw-in-c-r-a.html) +for more details about this behavior. + +1. Users aren't always familiar with offline-first web apps. It can be useful to + [let the user know](https://developers.google.com/web/fundamentals/instant-and-offline/offline-ux#inform_the_user_when_the_app_is_ready_for_offline_consumption) + when the service worker has finished populating your caches (showing a "This web + app works offline!" message) and also let them know when the service worker has + fetched the latest updates that will be available the next time they load the + page (showing a "New content is available once existing tabs are closed." message). Showing + this messages is currently left as an exercise to the developer, but as a + starting point, you can make use of the logic included in [`src/serviceWorker.js`](src/serviceWorker.js), which + demonstrates which service worker lifecycle events to listen for to detect each + scenario, and which as a default, just logs appropriate messages to the + JavaScript console. + 1. Service workers [require HTTPS](https://developers.google.com/web/fundamentals/getting-started/primers/service-workers#you_need_https), although to facilitate local testing, that policy [does not apply to `localhost`](http://stackoverflow.com/questions/34160509/options-for-testing-service-workers-via-http/34161385#34161385). If your production web server does not support HTTPS, then the service worker registration will fail, but the rest of your web app will remain functional. -1. Service workers are [not supported](https://jakearchibald.github.io/isserviceworkerready/#moar) - in older web browsers. Service worker registration [won't be attempted](src/serviceWorker.js) - on browsers that lack support. - 1. The service worker is only enabled in the [production environment](#deployment), e.g. the output of `npm run build`. It's recommended that you do not enable an offline-first service worker in a development environment, as it can lead to @@ -1919,18 +1935,6 @@ following into account: instructions for using other methods. _Be sure to always use an incognito window to avoid complications with your browser cache._ -1. Users aren't always familiar with offline-first web apps. It can be useful to - [let the user know](https://developers.google.com/web/fundamentals/instant-and-offline/offline-ux#inform_the_user_when_the_app_is_ready_for_offline_consumption) - when the service worker has finished populating your caches (showing a "This web - app works offline!" message) and also let them know when the service worker has - fetched the latest updates that will be available the next time they load the - page (showing a "New content is available; please refresh." message). Showing - this messages is currently left as an exercise to the developer, but as a - starting point, you can make use of the logic included in [`src/serviceWorker.js`](src/serviceWorker.js), which - demonstrates which service worker lifecycle events to listen for to detect each - scenario, and which as a default, just logs appropriate messages to the - JavaScript console. - 1. By default, the generated service worker file will not intercept or cache any cross-origin traffic, like HTTP [API requests](#integrating-with-an-api-backend), images, or embeds loaded from a different domain. diff --git a/template/src/serviceWorker.js b/template/src/serviceWorker.js index 46c98a44037..012c322dd2c 100644 --- a/template/src/serviceWorker.js +++ b/template/src/serviceWorker.js @@ -1,12 +1,14 @@ -// In production, we register a service worker to serve assets from local cache. +// This optional code is used to register a service worker. +// register() is not called by default. // This lets the app load faster on subsequent visits in production, and gives // it offline capabilities. However, it also means that developers (and users) -// will only see deployed updates on the "N+1" visit to a page, since previously -// cached resources are updated in the background. +// will only see deployed updates on subsequent visits to a page, after all the +// existing tabs open on the page have been closed, since previously cached +// resources are updated in the background. -// To learn more about the benefits of this model, read https://goo.gl/KwvDNy. -// This link also includes instructions on opting out of this behavior. +// To learn more about the benefits of this model and instructions on how to +// opt-in, read http://bit.ly/CRA-PWA. const isLocalhost = Boolean( window.location.hostname === 'localhost' || @@ -41,11 +43,11 @@ export function register(config) { navigator.serviceWorker.ready.then(() => { console.log( 'This web app is being served cache-first by a service ' + - 'worker. To learn more, visit https://goo.gl/SC7cgQ' + 'worker. To learn more, visit http://bit.ly/CRA-PWA' ); }); } else { - // Is not local host. Just register service worker + // Is not localhost. Just register service worker registerValidSW(swUrl, config); } }); @@ -61,11 +63,13 @@ function registerValidSW(swUrl, config) { installingWorker.onstatechange = () => { if (installingWorker.state === 'installed') { if (navigator.serviceWorker.controller) { - // At this point, the old content will have been purged and - // the fresh content will have been added to the cache. - // It's the perfect time to display a "New content is - // available; please refresh." message in your web app. - console.log('New content is available; please refresh.'); + // At this point, the updated precached content has been fetched, + // but the previous service worker will still serve the older + // content until all client tabs are closed. + console.log( + 'New content is available and will be used when all ' + + 'tabs for this page are closed. See http://bit.ly/CRA-PWA.' + ); // Execute callback if (config && config.onUpdate) {