Ankündigung

Einklappen
Keine Ankündigung bisher.

Service Worker SOFORT updaten

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Service Worker SOFORT updaten

    Hi,

    folgendes Szenario:

    Lade Website hoch, die mit Service Worker arbeitet:

    index.htm
    Code:
    <!DOCTYPE HTML>
    <html>
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="content-type" content="text/html" />
        <script type="text/javascript" src="main.js"></script>
        <title>Service Worker Test</title>
    </head>
    
    <body>
    <p>Hier ein Bild</p>
    <img src="pic1.png" style="width: 300px; height: auto;" />
    <p>Hier noch ein Bild</p>
    <img src="pic2.jpg"  width="300px;height:auto"/>
    
    </body>
    </html>
    main.js
    Code:
    if ('serviceWorker' in navigator) {
      navigator.serviceWorker.register('/sw-test/sw.js', { scope: '/sw-test/' }).then(function(reg) {
        // Registrierung erfolgreich
        console.log('Registrierung erfolgreich. Scope ist ' + reg.scope);
      }).catch(function(error) {
        // Registrierung fehlgeschlagen
        console.log('Registrierung fehlgeschlagen mit ' + error);
      });
    };
    sw.js
    Code:
    var currentCacheVersion = 'v1';
    
    this.addEventListener('install', function(event) {
      event.waitUntil(
        caches.open(currentCacheVersion).then(function(cache) {
          return cache.addAll([
            '/sw-test/',
            '/sw-test/index.htm',
            '/sw-test/main.js',
            '/sw-test/pic1.png',
            '/sw-test/pic2.jpg'
          ]);
        })
      );
    });
    
    this.addEventListener('fetch', function(event) {
      event.respondWith(
        caches.match(event.request).catch(function() {
          return fetch(event.request);
        })
      );
    });
    
    /* Delete all cached items that are not part of current cache version */
    this.addEventListener('activate', function(event) {
      var cacheWhitelist = [currentCacheVersion];
    
      event.waitUntil(
        caches.keys().then(function(keyList) {
          return Promise.all(keyList.map(function(key) {
            if (cacheWhitelist.indexOf(key) === -1) {
              return caches.delete(key);
            }
          }));
        })
      );
    });
    Das funktioniert bis hierhin ganz gut. Man kann in Chrome sehen, dass der Service Worker registriert ist und der Cache Storage entsprechend befüllt wird.
    Also erst mal alles gut.

    So, jetzt stelle ich 5 Minuten später fest, dass ich gar nicht pic1.png, sondern pic3.png auf der Website anzeigen möchte.

    Also ändere ich folgendes:

    index.htm: pic3 statt pic1
    Code:
    <p>Hier ein Bild</p>
    <img src="pic3.png" style="width: 300px; height: auto;" />
    <p>Hier noch ein Bild</p>
    <img src="pic2.jpg"  width="300px;height:auto"/>
    sw.js: Neue Versionsnummer und andere Dateilistung
    Code:
    var currentCacheVersion = 'v2';
    //...
    return cache.addAll([
            '/sw-test/',
            '/sw-test/index.htm',
            '/sw-test/main.js',
            '/sw-test/pic3.png',
            '/sw-test/pic2.jpg'
          ]);
    Das Ganze hochgeladen und

    Seite im Browser refreshen => keine Änderung sichtbar
    Browser schließen/öffnen/Seite aufrufen => keine Änderung sichtbar
    Strg+F5 drücken => "Erfolg", Änderungen werden sichtbar, ABER die Cache Version wird nicht upgedatet. Das geschieht erst, wenn ich in den DevTools beim Service Worker "Update on reload" anticke und dann nochmal refreshe.

    Das ist nur im Ergebnis nicht das, was ich will. Der Normaluser nutzt keine DevTools.

    So jetzt habe ich mir angelesen, dass man das "normale" Cachen der sw.js und vlt. auch der der index.htm unterbinden sollte.

    Also lege ich folgende .htaccess an:
    Code:
    <Files index.htm|sw.js|sw2.js>
    FileETag None
    Header unset ETag
    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>
    Das ändert aber leider gar nichts an dem oben beschriebenen Verhalten.

    Frage: Was muss ich tun, um die Änderungen SOFORT sichtbar zu machen UND den Cache SOFORT upzudaten?
    [B]Es ist schon alles gesagt. Nur noch nicht von allen.[/B]

  • #2
    Hi,
    habe inzwischen selber weiter geforscht und drei weitere Hinweise gefunden, die zusammen anscheinend das gewünschte Verhalten erzeugen. Ich nenne die hier jetzt mal nur lapidar. Wenn jemand dann noch Näheres wissen will, werde ich gerne - im Rahmen meiner Möglichkeiten - Weiteres mitteilen:

    1. Bei Installation des Service Workers: self.skipWaiting
    2. Bei Aktivierung des Service Workers: self.clients.claim
    3. Auf der Website: bei controllerchange-Ereignis einen Reload auslösen

    Habe es noch nicht ganz zu Ende getestet. Erste Versuche brachten allerdings vielversprechende Ergebnisse. D. h. Änderung an der Webapplikation werden SOFORT vom Browser umgesetzt.

    Was mich allgemein nur wundert ist, dass die im Web kursierenden "How Tos", "Getting started" etc. das Problem erst mal außen vor lassen, obwohl doch eigentlich klar sein sollte, dass nicht aktualisierbare Websites, Webapplikationen echt unbrauchbar sind.
    [B]Es ist schon alles gesagt. Nur noch nicht von allen.[/B]

    Kommentar


    • #3
      Schaue dir an wie andere das Caching umgehen.
      jquery hat die Versionsnummer im Dateinamen.
      Bei kleinen Änderungen, während der Entwicklung, hängst du einfach den Unix-Timespamp der Datei hinten dran.
      sw.js?=123456789

      Den Timestamp holst du dir aus http://php.net/manual/en/function.filemtime.php

      Header set Pragma "no-cache"
      Dieser Direktiven folgen die meisten Browser nicht.

      Lesestoff dazu: https://www.2uo.de/caching-tutorial/#expires
      Der ganze Artikel ist interessant.


      Kommentar


      • #4
        @protestix: Danke. Hatte ich völlig außer Acht gelassen, dass das so auch geht. Stimmt ja, da kann man sich .htacess - Einträge oder ähnliches sparen.

        Davon ab gibt es allerdings auch Situationen, in denen der Browser schon gemerkt hat, dass eine neue Cache Version - die Du ja über den angepassten Service Worker definierst, vorhanden ist.
        Da kann es dann sein, dass die Aktivierung der neuen CacheVersion hängt. Die Lösung dafür ist das "skip waiting" wobei ich allerdings zugeben muß, dass mir selber die Denkweise dahinter etwas
        schleierhaft ist.

        [B]Es ist schon alles gesagt. Nur noch nicht von allen.[/B]

        Kommentar


        • #5
          So, auch wenn sich hierfür nicht allzu viele Leute interessieren. Ich habe jetzt nach vielen Tests und DevTool-Beobachtungen eine Site mit Service Worker erstellen können, die wirklich das tut, was ich will.

          Was leider in allen Tutorials, die ich gelesen habe viel zu wenig bis gar nicht angesprochen wird, ist der Umgang mit dem "normalen" Browser Cache.

          Ein wichtiger Teil meiner Lösung geht dahin, dass man diesen gar nichts mehr speichern lässt. Meine Testsite wird außschließlich nur noch über den von mir angelegten Cache per Cache API bedient.

          Code:
          <FilesMatch "\.(css|flv|gif|htm|html|ico|jpe|jpeg|jpg|js|png|pdf|swf|txt)$">
              <IfModule mod_expires.c>
                  ExpiresActive Off
              </IfModule>
              <IfModule mod_headers.c>
                  FileETag None
                  Header unset ETag
                  Header unset Pragma
                  Header unset Cache-Control
                  Header unset Last-Modified
                  Header set Pragma "no-cache"
                  Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
                  Header set Expires "Mon, 10 Apr 1972 00:00:00 GMT"
              </IfModule>
          </FilesMatch>
          Macht man das nicht, ist es bei kurzfristigen, geschäftlich aber sehr wichtigen Änderungen an der Website, offenbar Glücksache, ob der Normaluser die Updates zu Gesicht bekommt.

          Zudem habe ich noch weitere Empfehlungen umgesetzt wie z. B. ein window.location.reload, wenn der neue Service Worker nach einem Update das Kommando übernommen hat.
          Diese Vorgehensweise ist aber nicht jedem Fall ratsam.

          Im Ergebnis habe ich folgendes erreicht:

          Eine Site, die offline funktioniert und SOFORT updated, wenn ich ein Update hochlade.

          Man sollte noch erwähnen, dass diese Lösung, einen richtigen funktionierenden Service Worker und Cache API Support voraussetzt. Stichwort Safari, wo die erste Implentierung anscheinend in die Hose gegangen ist.
          Für mich war das jetzt ers mal nur eine Übung, um vorbereitet zu sein, wenn die Browserhersteller den HTML5 Cache Manifest Support entfernen.
          [B]Es ist schon alles gesagt. Nur noch nicht von allen.[/B]

          Kommentar


          • #6
            Du könntest auch einfach TSL/SSL verwenden.

            Kommentar


            • #7
              Zitat von protestix Beitrag anzeigen
              Du könntest auch einfach TSL/SSL verwenden.
              Hm, verstehe ich nicht. Was hat TLS/SSL mit dem Thema zu tun?
              [B]Es ist schon alles gesagt. Nur noch nicht von allen.[/B]

              Kommentar


              • #8
                bei https URIs wird nichts im Browsercache abgelegt, insofern entspricht es deinen Anforderungen.

                Kommentar


                • #9
                  Zitat von protestix Beitrag anzeigen
                  bei https URIs wird nichts im Browsercache abgelegt, insofern entspricht es deinen Anforderungen.
                  Wie bitte? https://www.meinesite.de/index.html wird nicht im Browsercache abgelegt? Oder was willst Du damit sagen?
                  [B]Es ist schon alles gesagt. Nur noch nicht von allen.[/B]

                  Kommentar


                  • #10
                    Yes.

                    In fact nothing is being cached (on the persistent cache)...
                    Quelle: https://bugs.chromium.org/p/chromium...d=110649#c6%22

                    Für weitere Infos zum Cache mit HTT'P 1.1 bitte auch https://developers.google.com/web/fu...-caching?hl=de lesen.

                    Kommentar


                    • #11
                      @protestix: Äh, bist Du sicher, dass Du den richtigen Link gepostet hast.

                      Der Bug Report ist mehr als 6 Jahre alt und ist speziell für Chrome. Das Problem lag damals daran, dass unsaubere SSL Certificate benutzt wurden?

                      Any kind of SSL error will prevent us from caching anything from that site.

                      [B]Es ist schon alles gesagt. Nur noch nicht von allen.[/B]

                      Kommentar


                      • #12
                        Die Links sind so richtig.

                        Du verweist darauf, dass du dich nicht auf eine Aussage verlassen möchtest, die 6 Jahre alt ist. So weit so gut, Aber warum hast du dann pragma drin und wer garantiert dir, dass deine htaccess Anweisungen nach dem nächsten Browser-Update noch genau´so funktionieren?
                        Und was ist eigentlich mit Proxys?

                        Das Problem mit dem Caching ist so alt wie es Browser gibt.
                        Sicher ist nur eines, wenn du die URL deiner Ressource änderst muss der Browser diese erneut anfragen, da er diese mit denen im Cache vergleicht und wenn diese nicht vorhanden ist, hat der Browser keine Wahl, er muss die Ressource anfragen und ggf. den Content herunterladen.

                        Alles andere was so geschrieben steht, kann heute funktionieren, muss morgen aber nicht.

                        Kommentar

                        Lädt...
                        X