admin管理员组

文章数量:1427333

Bellow is how I register my serviceworker :

if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    function updateOnlineStatus() {
      SnackBar.show({
        text: navigator.onLine ? onlineMsg : offlineMsg,
        backgroundColor: '#000000',
        actionText: close,
        actionTextColor: '#d2de2f',
        customClass: 'custom-snackbar',
      });
    }
    window.addEventListener('online', updateOnlineStatus);
    window.addEventListener('offline', updateOnlineStatus);
    navigator.serviceWorker.register('sw.js').then((reg) => {
      reg.onupdatefound = () => {
        const installingWorker = reg.installing;
        installingWorker.onstatechange = () => {
          switch (installingWorker.state) {
            case 'installed':
              if (navigator.serviceWorker.controller) {
                SnackBar.show({
                  text: refreshMsg,
                  backgroundColor: '#000000',
                  actionText: refresh,
                  actionTextColor: '#d2de2f',
                  onActionClick: () => { location.reload(); },
                  customClass: 'custom-snackbar',
                });
              } else {
                console.info(availableMsg);
              }
              break;
            case 'redundant':
              console.info(redundantMsg);
              break;
            default:
              break;
          }
        };
      };
    }).catch((e) => {
      console.error(errorMsg, e);
    });
  });
}

This service-worker is generated during build by Workbox.

I'm a bit worried because these notifications are displayed on my puter (ubuntu + chrome 59.0.3071.115) however never on my mobile (android 6.0.1 + chrome 59.0.3071.125)

After analyzing with remote debugging feature, it looks like onupdatefound is never triggered on my mobile.

I feel very bad about UX, thinking about visitors on mobile that wouldn't know that a new version of website is pending ...

Any suggestion or advice will be appreciated


Edit 1 : I've found more details on "Browser Compatibility" section of this webpage : . It looks like support of this feature by Chrome for Android is unknown.

Do you guys have a kind of fallback / workaround when browser do not support onupdatefound event ?


Edit 2 : In response to Jeff,
sw.js header is managed in .htaccess file :

<Files sw.js>
  Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
  Header set Pragma "no-cache"
  Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT"
</Files>

which produces :

accept-ranges: bytes
cache-control: max-age=0, no-cache, no-store, must-revalidate
content-encoding: br
content-language: fr-FR
content-length: 1636
content-type: application/javascript; charset=utf-8
date: Fri, 21 Jul 2017 13:04:06 GMT
expires: Wed, 11 Jan 1984 05:00:00 GMT
last-modified: Tue, 18 Jul 2017 02:58:30 GMT
pragma: no-cache

Regarding workbox fine tuning you suggest, I didn't find time to dig in yet so i'm using the easy workbox-build in a gulp file. But I hopefully will :)

// Service Worker generation
gulp.task('bundle-sw', gulp.series('generate-sitemap', () => {
  return wbBuild.generateSW({
    globDirectory: gulpOutputDir,
    swDest: `${gulpOutputDir}/sw.js`,
    globPatterns: ['**/*.{html,png,xml,css,ico,txt,json,svg,js,map,gif,jpeg,jpg,bmp,cur,webp,woff2}'],
    skipWaiting: true,
    clientsClaim: true,
  })
  .then(() => {
    console.warn('Service worker generated.');
  })
  .catch((err) => {
    console.error(`[ERROR] This happened: ${err}`);
  });
}));

Do you think it could be caused by skipWaiting: true ?


Edit 3 : Trying with BroadcastChannel

navigator.serviceWorker.register('/sw.js').then((reg) => {
  console.log('test');
  const updateChannel = new BroadcastChannel('precache-updates');
  updateChannel.addEventListener('message', event => {
    console.log(`Cache updated: ${event.data.payload.updatedUrl}`);
  });
}).catch((e) => {
  console.error(errorMsg, e);
});

Even if test is outputed in log on Chrome, mobile, or firefox, update messages are only thrown on Chrome

Bellow is how I register my serviceworker :

if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    function updateOnlineStatus() {
      SnackBar.show({
        text: navigator.onLine ? onlineMsg : offlineMsg,
        backgroundColor: '#000000',
        actionText: close,
        actionTextColor: '#d2de2f',
        customClass: 'custom-snackbar',
      });
    }
    window.addEventListener('online', updateOnlineStatus);
    window.addEventListener('offline', updateOnlineStatus);
    navigator.serviceWorker.register('sw.js').then((reg) => {
      reg.onupdatefound = () => {
        const installingWorker = reg.installing;
        installingWorker.onstatechange = () => {
          switch (installingWorker.state) {
            case 'installed':
              if (navigator.serviceWorker.controller) {
                SnackBar.show({
                  text: refreshMsg,
                  backgroundColor: '#000000',
                  actionText: refresh,
                  actionTextColor: '#d2de2f',
                  onActionClick: () => { location.reload(); },
                  customClass: 'custom-snackbar',
                });
              } else {
                console.info(availableMsg);
              }
              break;
            case 'redundant':
              console.info(redundantMsg);
              break;
            default:
              break;
          }
        };
      };
    }).catch((e) => {
      console.error(errorMsg, e);
    });
  });
}

This service-worker is generated during build by Workbox.

I'm a bit worried because these notifications are displayed on my puter (ubuntu + chrome 59.0.3071.115) however never on my mobile (android 6.0.1 + chrome 59.0.3071.125)

After analyzing with remote debugging feature, it looks like onupdatefound is never triggered on my mobile.

I feel very bad about UX, thinking about visitors on mobile that wouldn't know that a new version of website is pending ...

Any suggestion or advice will be appreciated


Edit 1 : I've found more details on "Browser Compatibility" section of this webpage : https://developer.mozilla/en-US/docs/Web/API/ServiceWorkerRegistration/onupdatefound. It looks like support of this feature by Chrome for Android is unknown.

Do you guys have a kind of fallback / workaround when browser do not support onupdatefound event ?


Edit 2 : In response to Jeff,
sw.js header is managed in .htaccess file :

<Files sw.js>
  Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
  Header set Pragma "no-cache"
  Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT"
</Files>

which produces :

accept-ranges: bytes
cache-control: max-age=0, no-cache, no-store, must-revalidate
content-encoding: br
content-language: fr-FR
content-length: 1636
content-type: application/javascript; charset=utf-8
date: Fri, 21 Jul 2017 13:04:06 GMT
expires: Wed, 11 Jan 1984 05:00:00 GMT
last-modified: Tue, 18 Jul 2017 02:58:30 GMT
pragma: no-cache

Regarding workbox fine tuning you suggest, I didn't find time to dig in yet so i'm using the easy workbox-build in a gulp file. But I hopefully will :)

// Service Worker generation
gulp.task('bundle-sw', gulp.series('generate-sitemap', () => {
  return wbBuild.generateSW({
    globDirectory: gulpOutputDir,
    swDest: `${gulpOutputDir}/sw.js`,
    globPatterns: ['**/*.{html,png,xml,css,ico,txt,json,svg,js,map,gif,jpeg,jpg,bmp,cur,webp,woff2}'],
    skipWaiting: true,
    clientsClaim: true,
  })
  .then(() => {
    console.warn('Service worker generated.');
  })
  .catch((err) => {
    console.error(`[ERROR] This happened: ${err}`);
  });
}));

Do you think it could be caused by skipWaiting: true ?


Edit 3 : Trying with BroadcastChannel

navigator.serviceWorker.register('/sw.js').then((reg) => {
  console.log('test');
  const updateChannel = new BroadcastChannel('precache-updates');
  updateChannel.addEventListener('message', event => {
    console.log(`Cache updated: ${event.data.payload.updatedUrl}`);
  });
}).catch((e) => {
  console.error(errorMsg, e);
});

Even if test is outputed in log on Chrome, mobile, or firefox, update messages are only thrown on Chrome

Share Improve this question edited Aug 5, 2017 at 2:22 LIIT asked Jul 18, 2017 at 12:42 LIITLIIT 6149 silver badges17 bronze badges 1
  • developers.google./web/fundamentals/instant-and-offline/… u may want to revise your observer after reviewing the docs. – Robert Rowntree Commented Jul 19, 2017 at 23:13
Add a ment  | 

2 Answers 2

Reset to default 2

There shouldn't be any difference in the service worker implementation in Chrome on Android and Linux that would account for one platform not having the updatefound event exposed on a service worker registration. (MDN isn't necessarily authoritative here.)

Whenever I've debugged this sort of unpredictable updates in the past, it's been due to interactions with the HTTP cache and the sw.js script. Can you check to see what Cache-Control headers you're using when you serve sw.js?

Also, you mention that you're using Workbox—you have access to a more advanced approach to checking for updated resources if that's the case. The workbox-broadcast-cache-update plugin (which is enabled by default if you're using workbox-sw's precache() method) can announce when a specific cached resource is updated, and then you can listen for that message on your page using the Broadcast Channel API. This allows you to only show your SnackBar when the most important resources change—like the HTML—rather than less important resources, like random images that might be precached.

As you suspected, problem didn't e at all from Service Worker by itself.

I started from scratch and tried to identify the origin of this issue, adding code piece by piece until no more event is exposed. I figured it out : it was because of an "expensive" loop used in a three.js animation.

After puting this piece of code in a worker, my page is now able to catch these events on mobile or Firefox and user's notification works just fine !

About the confusing fact that it was working on desktop version of Chrome, I guess it's because it must support multithreading ...

Thanks again for your help :)

本文标签: javascriptserviceworker onupdatefound not triggered on mobileStack Overflow