Wie kann ich einen fehlerhaften Servicemitarbeiter entfernen oder einen "Kill-Schalter" implementieren?

71

Ich spiele mit der Service Worker-API in meinem Computer, damit ich verstehen kann, wie ich in meinen realen Apps davon profitieren kann.

Ich bin auf eine seltsame Situation gestoßen, in der ich einen Servicemitarbeiter registriert habe, der das Abrufereignis abfängt , damit er seinen Cache auf angeforderten Inhalt überprüfen kann, bevor er eine Anforderung an den Ursprung sendet. Das Problem ist, dass dieser Code einen Fehler aufweist, der die Funktion daran gehindert hat, die Anforderung zu stellen, sodass meine Seite leer bleibt. nichts passiert. Da der Servicemitarbeiter registriert wurde, fängt er beim zweiten Laden der Seite die allererste Anforderung ab (diejenige, die den HTML-Code lädt). Da ich diesen Fehler habe, schlägt dieses Abrufereignis fehl, es fordert nie den HTML-Code an und alles, was ich sehe, ist eine leere Seite.

In dieser Situation kann ich das Skript für fehlerhafte Servicemitarbeiter nur über die chrome://serviceworker-internals/Konsole entfernen . Wenn dieser Fehler auf eine Live-Website gelangt, wie kann er am besten behoben werden?

Vielen Dank!

PaquitoSoft
quelle

Antworten:

98

Ich wollte einige der anderen Antworten hier erweitern und dies unter dem Gesichtspunkt betrachten: "Welche Strategien kann ich anwenden, wenn ich einen Servicemitarbeiter in die Produktion einbringe, um sicherzustellen, dass ich die erforderlichen Änderungen vornehmen kann?" Diese Änderungen können das Beheben kleinerer Fehler umfassen, die Sie in der Produktion entdecken, oder das Neutralisieren des Servicemitarbeiters aufgrund eines unüberwindlichen Fehlers - eines sogenannten "Kill-Schalters".

Nehmen wir für diese Antwort an, Sie rufen an

navigator.serviceWorker.register('service-worker.js');

auf Ihren Seiten, dh Ihre Service-Worker-JavaScript-Ressource ist service-worker.js. ( Siehe unten, wenn Sie nicht sicher sind, welche URL des Service Workers genau verwendet wurde - möglicherweise, weil Sie dem Service Worker-Skript einen Hash oder Versionsinformationen hinzugefügt haben. )

Die Frage läuft darauf hinaus, wie Sie das ursprüngliche Problem in Ihrem service-worker.jsCode lösen . Wenn es sich um eine kleine Fehlerbehebung handelt, können Sie die Änderung natürlich einfach vornehmen und sie erneut service-worker.jsin Ihrer Hosting-Umgebung bereitstellen . Wenn es keine offensichtlichen Fehler zu beheben ist, und Sie nicht möchten , dass Ihre Benutzer, die den Buggy - Service Arbeitnehmer Code zu lassen , während Sie die Zeit , um Arbeit aus einer Lösung nehmen, ist es eine gute Idee , eine möglichst einfach zu halten, no-op service-worker.js handlich , wie die Folgendes:

// A simple, no-op service worker that takes immediate control.

self.addEventListener('install', () => {
  // Skip over the "waiting" lifecycle state, to ensure that our
  // new service worker is activated immediately, even if there's
  // another tab open controlled by our older service worker code.
  self.skipWaiting();
});

/*
self.addEventListener('activate', () => {
  // Optional: Get a list of all the current open windows/tabs under
  // our service worker's control, and force them to reload.
  // This can "unbreak" any open windows/tabs as soon as the new
  // service worker activates, rather than users having to manually reload.
  self.clients.matchAll({type: 'window'}).then(windowClients => {
    windowClients.forEach(windowClient => {
      windowClient.navigate(windowClient.url);
    });
  });
});
*/

Das sollte alles sein, was Ihr No-Op service-worker.jsenthalten muss. Da kein fetchHandler registriert ist, werden alle Navigations- und Ressourcenanforderungen von kontrollierten Seiten direkt an das Netzwerk weitergeleitet, sodass Sie das gleiche Verhalten erhalten, ohne das Sie ohne einen Servicemitarbeiter auskommen würden.

Zusätzliche Schritte

Es ist möglich, weiter zu gehen und alles, was mit der Cache-Speicher-API gespeichert wurde, zwangsweise zu löschen oder die Registrierung des Service-Workers explizit vollständig aufzuheben. In den meisten Fällen ist dies wahrscheinlich ein Overkill. Die Befolgung der oben genannten Empfehlungen sollte ausreichen, um Sie in einen Zustand zu versetzen, in dem Ihre aktuellen Benutzer das erwartete Verhalten erhalten, und Sie können Updates erneut bereitstellen, sobald Sie Ihre Fehler behoben haben . Das Starten eines No-Op-Service-Workers ist mit einem gewissen Aufwand verbunden. Sie können also die Registrierung des Service-Workers aufheben, wenn Sie nicht vorhaben, einen aussagekräftigen Service-Worker-Code erneut bereitzustellen.

Wenn Sie sich bereits in einer Situation befinden, in der Sie service-worker.jsmit HTTP-Caching-Direktiven arbeiten, die eine Lebensdauer haben, die länger ist, als Ihre Benutzer warten können, denken Sie daran, dass Shift + Reload in Desktop-Browsern das Neuladen der Seite außerhalb von erzwingt Kontrolle der Servicemitarbeiter. Nicht jeder Benutzer weiß, wie das geht, und auf Mobilgeräten ist dies jedoch nicht möglich. Verlassen Sie sich also nicht auf Shift + Reload als praktikablen Rollback-Plan.

Was ist, wenn Sie die URL des Servicemitarbeiters nicht kennen?

Bei den obigen Informationen wird davon ausgegangen service-worker.js, dass Sie die URL des Servicemitarbeiters kennen sw.js- oder etwas anderes, das effektiv konstant ist. Aber was ist, wenn Sie eine Art Versions- oder Hash-Information in Ihr Service Worker-Skript aufgenommen haben, wie z service-worker.abcd1234.js.

Versuchen Sie zunächst, dies in Zukunft zu vermeiden - dies verstößt gegen Best Practices . Wenn Sie jedoch bereits eine Reihe versionierter Service-Worker-URLs bereitgestellt haben und die Dinge für alle Benutzer deaktivieren müssen , unabhängig davon, welche URL sie möglicherweise registriert haben, gibt es einen Ausweg.

Jedes Mal, wenn ein Browser eine Anforderung für ein Service Worker-Skript stellt, unabhängig davon, ob es sich um eine Erstregistrierung oder eine Aktualisierungsprüfung handelt, wird ein HTTP-Anforderungsheader namens aufgerufen Service-Worker:.

Angenommen, Sie haben die volle Kontrolle über Ihren Back-End-HTTP-Server, können Sie eingehende Anforderungen auf das Vorhandensein dieses Service-Worker:Headers überprüfen und unabhängig von der Anforderungs-URL immer mit der Skriptantwort Ihres No-Op-Service-Workers antworten.

Die Besonderheiten der Konfiguration Ihres Webservers variieren von Server zu Server.

Der Clear-Site-Data: Antwortheader

Ein letzter Hinweis: Einige Browser löschen automatisch bestimmte Daten und heben möglicherweise die Registrierung von Servicemitarbeitern auf, wenn ein spezieller HTTP-Antwortheader als Teil einer Antwort zurückgegeben wird : Clear-Site-Data:.

Das Festlegen dieses Headers kann hilfreich sein, wenn Sie versuchen, eine fehlerhafte Service Worker-Bereitstellung wiederherzustellen. Kill-Switch-Szenarien sind in der Spezifikation der Funktion als Beispiel für einen Anwendungsfall enthalten.

Es ist wichtig , die zu überprüfen Browser - Unterstützung Geschichte für , Clear-Site-Data:bevor Sie verlassen sich ausschließlich auf sie als Kill-Switch. Ab Juli 2019 wird es nicht in 100% der Browser unterstützt, die Servicemitarbeiter unterstützen. Daher ist es derzeit am sichersten, es Clear-Site-Data:zusammen mit den oben genannten Techniken zu verwenden, wenn Sie Bedenken haben, sich in allen Browsern von einem fehlerhaften Servicemitarbeiter zu erholen.

Jeff Posnick
quelle
10

Sie können die Registrierung des Servicemitarbeiters mithilfe von Javascript aufheben. Hier ist ein Beispiel:

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.getRegistrations().then(function (registrations) {
    //returns installed service workers
    if (registrations.length) {
      for(let registration of registrations) {
        registration.unregister();
      }
    }
  });
}
Prasanna Jathan
quelle
1
Dies muss vor der .registe Methode stehen, damit die Registrierung aller zuvor registrierten Benutzer aufgehoben wird, oder kann sie überall ausgeführt werden?
DiEcho
8

Das ist eine wirklich schlimme Situation, die Ihnen in der Produktion hoffentlich nicht passieren wird.

In diesem Fall fallen mir zwei Dinge ein , wenn Sie nicht die Entwicklertools der verschiedenen Browser, chrome://serviceworker-internals/für blinkbasierte Browser oder about:serviceworkers( about:debugging#workersin Zukunft) in Firefox durchgehen möchten :

  1. Verwenden Sie den Wartungsmechanismus für Servicemitarbeiter. Ihr Benutzeragent prüft, ob Änderungen am registrierten Mitarbeiter vorgenommen wurden, ruft diese ab und durchläuft die activatePhase erneut. So können Sie möglicherweise das Serviceworker-Skript ändern, jede seltsame Situation beheben (Caches löschen usw.) und weiterarbeiten. Der einzige Nachteil ist, dass Sie warten müssen, bis der Browser den Worker aktualisiert, was 1 Tag dauern kann.
  2. Fügen Sie Ihrem Arbeiter eine Art Kill-Schalter hinzu . Sie haben eine spezielle URL, über die Sie Benutzer auf einen Besuch verweisen können, um den Status Ihrer Caches usw. wiederherzustellen.

Ich bin nicht sicher, ob das Löschen Ihrer Browserdaten den Worker entfernt, sodass dies eine weitere Option sein könnte.

Francisco Jordano
quelle
1
Danke für deine Antwort. Option 1 ist für eine Live-Website nicht erschwinglich. Ich werde einen Blick auf Option 2 werfen, aber ich bin nicht sehr sicher, ob es funktionieren würde, wenn Sie Ihren Servicemitarbeiter auf Ihrer Website auf höchster Ebene ("/")
registrieren würden
4

Ich habe dies nicht getestet, aber es gibt eine unregister () - und eine update () -Methode für das ServiceWorkerRegistration-Objekt. Sie können dies vom navigator.serviceWorker erhalten.

navigator.serviceWorker.getRegistration('/').then(function(registration) {
  registration.update();
});

Das Update sollte dann sofort prüfen, ob ein neuer Servicetechniker vorhanden ist, und ihn gegebenenfalls installieren. Dadurch wird die Wartezeit von 24 Stunden umgangen und die Datei serviceworker.js wird jedes Mal heruntergeladen, wenn dieses Javascript auftritt.

Marco Tolk
quelle
3

In Live-Situationen müssen Sie den Servicemitarbeiter auf Byte-Ebene ändern (z. B. in der ersten Zeile einen Kommentar einfügen). Dieser wird in den nächsten 24 Stunden aktualisiert . Sie können dies mit dem Chrome emulieren: // serviceworker-internals / in Chrome, indem Sie auf die Schaltfläche Aktualisieren klicken .

Dies sollte auch in Situationen funktionieren, in denen der Servicemitarbeiter selbst zwischengespeichert wurde, als in Schritt 9 des Aktualisierungsalgorithmus ein Flag gesetzt wurde, um den Servicemitarbeiter zu umgehen.

Salva
quelle
0

Für den Fall, dass es jemand anderem hilft, habe ich versucht, Servicemitarbeiter zu töten, die in Browsern ausgeführt wurden, die eine Produktionsstätte erreicht hatten, auf der sie registriert wurden. Ich habe es gelöst, indem ich eine service-worker.js veröffentlicht habe, die genau Folgendes enthielt:

self.globalThis.registration.unregister();

Craig Fisher
quelle
Das kann 24 Stunden oder länger dauern? Sieht aber sonst ok aus. stackoverflow.com/questions/38843970/…
Tom Andersen
0

Wir hatten eine Site von godaddy.com auf eine reguläre WordPress-Installation verschoben. Der Client (nicht wir) hatte eine Servicearbeiterdatei (sw.js) in all seinen Browsern zwischengespeichert, was die Dinge völlig durcheinander brachte. Unsere Site, eine normale WordPress-Site, hat keine Servicemitarbeiter.

Es ist wie ein Virus, da es auf jeder Seite nicht von unserem Server stammt und es keine Möglichkeit gibt, ihn einfach loszuwerden.

Wir haben eine neue leere Datei mit dem Namen sw.js im Stammverzeichnis des Servers erstellt und dann jeder Seite auf der Site Folgendes hinzugefügt.

<script>
if (navigator && navigator.serviceWorker && navigator.serviceWorker.getRegistration) {

    navigator.serviceWorker.getRegistration('/').then(function(registration) {
        if (registration) {
              registration.update();
              registration.unregister();
        }
});

}
</script>
Tom Andersen
quelle
Wir hatten dies auf einer anderen Site (derselbe Client, auf dem sie Sites auf Godaddy hatten) - es gibt einen Fehler in Browsern. Wenn der Update-Mechanismus einen 404 für einen Servicemitarbeiter erhält, verwendet er den Alten! Also musst du eins machen.
Tom Andersen