2017-08-15 2 views
2

Ich verwende einen Service-Mitarbeiter, um die JS- und CSS-Dateien einer Web-App zwischenzuspeichern. Ich verwende meistens den Code aus einem Google Chrome-Beispiel. Das einzige, was ich hinzugefügt habe, ist eine Benachrichtigung und ein Countdown, der das Fenster aktualisiert, wenn "neuer oder aktualisierter Inhalt verfügbar ist".Service Worker "installiert" mit jedem Neuladen der Seite, obwohl sich die sw.js nicht geändert hat

Das Google-Beispiel: https://github.com/GoogleChrome/sw-precache/blob/5699e5d049235ef0f668e8e2aa3bf2646ba3872f/demo/app/js/service-worker-registration.js

Dies ist jedoch viel zu oft passiert, und ich verstehe nicht, warum. Es gab definitiv keine Änderungen an den Dateien auf dem Server, aber manchmal sehe ich die Benachrichtigung und das Fenster neu geladen.

Ich erwartete, dass dies nur passieren würde, wenn sich irgendeine der vom Service-Arbeiter geregelten Dateien tatsächlich ändert (sie sind alle über Webpack gehashed und haben sich definitiv zwischenzeitlich nicht geändert).

Dies ist der Code, den ich verwende, inlined in index.html:

/* eslint-env browser */ 
'use strict'; 
function reloadApp(delay) { 
    var t = delay || 0; 
    var message = 'New or updated content is available. Reloading app in {s} seconds'; 
    var getMessage = function() { return message.replace('{s}', t) } 
    var div = document.createElement('div'); 
    div.id = 'update-notification'; 
    div.innerHTML = getMessage(); 
    document.body.appendChild(div); 
    var intervalID = setInterval(function() { 
    t = t - 1; 
    if (t <= 0) { 
     clearInterval(intervalID); 
     window.location.reload(); 
    } 
    else { 
     div.innerHTML = getMessage(); 
    } 
    }, 1000); 
} 
if ('serviceWorker' in navigator && window.location.protocol === 'https:') { 
    navigator.serviceWorker.register('/service-worker.js').then(function(reg) { 
    console.info('serviceWorker registered'); 
    reg.onupdatefound = function() { 
     var installingWorker = reg.installing; 
     installingWorker.onstatechange = function() { 
     switch (installingWorker.state) { 
      case 'installed': 
      if (navigator.serviceWorker.controller) { 
       reloadApp(5); 
      } else { 
       console.log('Content is now available offline!'); 
      } 
      break; 

      case 'redundant': 
      console.error('The installing service worker became redundant.'); 
      break; 
     } 
     }; 
    }; 
    }).catch(function(e) { 
    console.error('Error during service worker registration:', e); 
    }); 
} 

Dies ist die Veränderung, die ich gemacht:

switch (installingWorker.state) { 
    case '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 the page's interface. 
     console.log('New or updated content is available.'); 
    } else { 

wurde:

switch (installingWorker.state) { 
    case 'installed': 
    if (navigator.serviceWorker.controller) { 
     reloadApp(5); 

Der Service Arbeiter selbst ist generiert über sw-precache-webpack-plugin und die Hash-Dateien sehen so aus:

var precacheConfig = [["cms.CrudFactory.144344a2.js","6a65526f764f3caa4b8c6e0b84c1b31b"],["cms.routes.c20796b4.js","f8018476ceffa8b8f6ec00b297a6492d"],["common.cms-main.0f2db9ff.js","92017e838aff992e9f47f721cb07b6f0"],["common.licensing-main.8000b17d.js","0d43abd063567d5edaccdcf9c0e4c362"],["common.mediaplayer-main.314be5d2.js","2061501465a56e82d968d7998b9ac364"],["common.ordering-main.783e8605.js","0531c4a90a0fa9ea63fbe1f82e86f8c6"],["common.shared-main.0224b0ea.js","956ae4d2ddbddb09fb51804c09c83b22"],["common.stores-main.98246b60.js","cbdc46bc3abeac89f37e8f64b1737a22"],["component.App.284fec19.js","07f1923f1a0098bf9eba28fc7b307c18"],["component.AppToolbar.00e371de.js","9b542d4a85bdeece9d36ee4e389f6206"],["component.DevToolbar.652bf856.js","1744126e32774a93796146ac878ddd8e"],["component.Grid.4b964e52.js","755819ca2c7f911805e372401d638351"],["component.MediaPlayer.54db6e85.js","d0d8ae269665e810d1b997b473005f76"],["component.Search.05476f89.js","0cae8928aff533a6726dfaeb0661456a"],["data.country-list.d54f29a7.js","e27746418e02f75593a93b958a60807e"],["dev.sendSlackMessage.da8e22f4.js","ccb10829f18a727b79a5e8631bc4b2a2"],["index.html","02ff43eabc33c600e98785cffe7597d9"],["lib.gemini-scrollbar.df2fbf63.js","3941036bacb4a1432d22151ea7da073b"],["lib.isotope-horizontal.1604d974.js","6ac56d4296468c4428b5b5301a65938a"],["lib.isotope-packery.fabb73c3.js","808061641596e4b0ea2158b42d65915a"],["lib.react-color.265a6de0.js","f23f63d7e6934e381ffdc0405ecb449a"],["lib.react-date-picker.0a81fec3.js","778d1626645e439ad01e182ee589971a"],["lib.react-select.c768cf77.js","c8782991a161790ef2c9a2c7677da313"],["main.43e29bc6.js","fe6a6277acaa2a369ef235961be7bbcf"],["route.admin.CleanupPage.8b4bbf8e.js","8ab20412329e1ba4adc327713135be97"],["route.app.CmsPage.8a4303fb.js","0bf1506869db24bb9789c8a46449c8ad"],["route.app.CmsPageWrapper.accdebcc.js","c91e77aa8b518e1878761269deac22b6"],["route.app.ContactPage.75693d32.js","a530b00a5230a44897c2bf0aa9f402a8"],["route.app.PasswordResetExpiredDialog.65431bae.js","b5eef791dbd68edd4769bd6da022a857"],["route.app.SeriesDetailsPage.11a6989b.js","c52178b57767ae1bf94a9594cb32718e"],["route.cms.MetadataFormsPage.636188d2.js","e1e592b7e3dd82af774ac215524465c0"],["route.cms.PermissionsListPage.0e1e3075.js","9a3cc340a64238a1ab3ba1c0d483b7bd"],["route.cms.PermissionsPage.78a69f60.js","4b18e646715d6268e7aba3932f4e04a9"],["route.cms.SysconfigPage.f699b871.js","79bd1275213478f2ff1970e0b7341c49"],["styles.43e29bc620615f854714.css","b2e9e55e9ee2def2ae577ee1aaebda8f"],["styles.e0c12bb1c77e645e92d3.css","626778177949d72221e83b601c6c2c0f"],["translations.en.83fced0e.js","7e5509c23b5aafc1744a28a85c2950bb"],["translations.nl.4ae0b3bb.js","515ec7be7352a0c61e4aba99f0014a39"],["vendor.e0c12bb1.js","36ce9e0a59c7b4577b2ac4a637cb4238"]]; 
var cacheName = 'sw-precache-v3-nisv-client-' + (self.registration ? self.registration.scope : ''); 

Fragen:

  • Warum ist die 'neue oder aktualisierte Inhalte' Happening Fall so oft?
  • Ist die Annahme richtig, dass case 'installed': if (navigator.serviceWorker.controller) { bedeutet New or updated content is available?
  • Wie sollte ich das Problem debuggen?
+0

1. Wird der statische Inhalt geändert, die Datei erneut geöffnet und ein Update für Ihren Service-Mitarbeiter ausgelöst? 2. Haben Sie 'update on reload' aktiviert? –

Antwort

1

hat ein Servicemitarbeiter ein life cycle:

- registered 
- installing 
- installed 
- waiting 
- activated 
- redundant 

Wenn Sie einen Servicemitarbeiter registrieren, ist es vom Server geholt, und es ist die Lebensdauer im disk Cache hängt von den cache-control Antwort-Header, dass Ihre Web Server sendet es mit.

Es gilt als Best Practice, wenn möglich einen cache-control : no-store must-revalidate zusammen mit einem max-age : 0 zu haben.

Wenn Sie vergessen haben, wird der Service-Mitarbeiter nach 24 Stunden der Registrierung normalerweise als stale betrachtet und wird refetched und Disk-Caches aktualisiert.

Es gibt manuelle Upgrades, die Sie tun können, indem Sie eine cache Version auf dem Service-Arbeiter stoßen oder den Service-Worker-Code ändern. Sogar eine byte Änderung macht den Browser view der Service-Mitarbeiter als ein neuer, und es installiert den neuen Service-Arbeiter.

Dies bedeutet jedoch nicht, dass der alte Service-Mitarbeiter verworfen wird.Es ist zwingend notwendig, dass alle Benutzer schließen aller Tabs/navigate von Ihrer Website entfernt, für den Browser zu Verwerfungs der alten Servicemitarbeiter und aktivieren die neuen.

Sie dieses Verhalten umgehen können, durch eine self.skipWaiting in Ihrem install handler

Das heißt,

Bei der Entwicklung, Sie haben die Möglichkeit, den Browser-Öffnung (Chrom) dev Panel, navigieren Sie zu dem application Registerkarte und überprüfen Sie die Box, die

update on reload

sagt Was dies bedeutet ist, sofort Verwerfen Sie den alten Service-Mitarbeiter unabhängig davon, ob sich Ihr Service-Worker-Code geändert hat.

In Bezug auf Ihre Fragen:

  • die Annahme, dass Fall korrigieren 'installed': if (navigator.serviceWorker.controller) {bedeutet neue oder aktualisierte Inhalte zur Verfügung steht?

NR. Dies bedeutet, dass der neue Service-Mitarbeiter, z. B. sw-v1, installiert ist und derzeit waiting aktiviert ist.

  • Warum ist die 'neue oder aktualisierte Inhalte' Happening Fall so oft?

Sie sagen, Sie sw-precache verwenden. Da habe ich es selbst nicht verwendet wird, muss ich hinzufügen, eine Gegenfrage

  • Ist das Plugin konfiguriert, um Änderungen an der statischen Vermögenswerte zu holen und automatisch eine Codeänderung oder einen Cache Beule auslösen in Ihrem service-worker?

Wenn ja, dann wird jede neue Version Ihrer Servicemitarbeiter, nur waiting sein muss und nicht activating auf einen Wechsel.

Der wahrscheinliche Grund für diese skipping der Wartephase haben

  • ist es, Ihnen eine self.skipWaiting in Ihrem install Ereignis in Ihrem Servicemitarbeiter.

Hinweis die oben gilt nur, wenn

  • die Änderung, um Ihre Inhalte geschieht.UND
  • das Update löst einen Servicemitarbeiter

In diesem Szenario ändern, könnten Sie die self.skipWaiting Aussage kommentieren heraus zu betrachten. Oder vielleicht könnten Sie Ihr Plugin konfigurieren, nicht auf Update überspringen - das auf dem Inhalt zählt, und Sie müssen einen Anruf

Anstelle der Tatsache zu ziehen, dass Ihr Vermögen geändert und/oder ausgelöst Update,

der andere (am wahrscheinlichsten) Grund sein müßte,

Sie haben eine update on reload Box unter den application geprüft ->service workers Registerkarte auf Ihrer dev-Konsole.

Deaktivieren Sie dieses Kontrollkästchen, wenn dies aktiviert ist, und löschen Sie dann alle Caches, heben Sie die Registrierung aller Worker auf. Danach öffnen Sie eine neue Registerkarte und testen Sie das Verhalten weiter.

Verwandte Themen