So erhalten Sie einen Jekyll-Blog, der mithilfe von Servicemitarbeitern offline funktioniert

Veröffentlicht: 2017-01-26

Short Bytes: Wussten Sie, dass man mit dem Aufkommen von Service Workern damit beginnen könnte, Websites offline zu betreiben? Solche Web-Apps werden als PWAs (Progressive Web Apps) bezeichnet. In dieser Anleitung werde ich Ihnen helfen, einen Servicemitarbeiter einzusetzen, um einen Jekyll-basierten Blog/eine Jekyll-basierte Website offline zum Laufen zu bringen, und einige coole Dinge, die damit einhergehen.

(HINWEIS : Die Codeausschnitte in dem Artikel stammen aus dem Code-Repository meines Blogs. Bei Bedarf kann darauf verwiesen werden. Wenn Sie neu bei Jekyll sind, können Sie den Artikel der 3er-Serie über CSS-Tricks lesen.)

HINTERGRUND

Früher gab es einen auf Yuk-YAML-Dateien basierenden App-Cache, der von Natur aus sehr hart codiert war und nicht zum dynamischen Zwischenspeichern von Assets und Webseiten verwendet werden konnte. Treten Sie ein, Servicemitarbeiter. Einfache, einfache, ereignisbasierte Javascript-API zum dynamischen Zwischenspeichern von Service-Workern zum Speichern von Assets, sodass sie zum Bereitstellen der Webseiten verwendet werden können, wenn kein Netzwerk vorhanden ist.

Servicemitarbeiter landeten 2014 in Chrome Canary, aber die Spezifikation wird noch überarbeitet/ergänzt und gestaltet. In den Jahren 2015 und 2016 hat das Chrome-Team von Google diese neue Technologie in den Browsern stark verbreitet. Nur Apple hat dies (selbst zum Zeitpunkt des Schreibens dieses Artikels) auf seinen Geräten (aus unbekannten Gründen) nicht unterstützt [Sie beteiligen sich auch nicht aktiv an irgendwelchen Diskussionen über Spezifikationen über Servicemitarbeiter].

Was ist ein Servicemitarbeiter? Im Grunde ist es ein Webworker auf Steroiden. Ein Merkmal eines Webworkers besteht darin, dass alle Aufgaben eines Webworkers separat (asynchron) vom Haupt-JavaScript-Ausführungsthread (Ereignisschleife) ausgeführt werden. Diese Funktion hilft bei der Ausführung von CPU- oder speicherintensiven Aufgaben, z. B. komplizierten Berechnungen, ohne die Leistung Ihrer Benutzeroberfläche der Web-App zu beeinträchtigen.

Mit Service Worker können wir Assets wie JavaScript-, CSS-, HTML-, Bild- und Schriftartdateien im Service Worker-Cache des Browsers zwischenspeichern (für lange Zeit speichern), sodass sie beim nächsten Laden dieser Seite fast sofort geladen wird . Und da bei dieser Caching-Strategie der Browser die Verfügbarkeit der Assets zuerst aus dem Service-Worker-Cache sucht, wird die Webseite auch dann bereitgestellt, wenn man offline ist! Wenn ein Asset nicht im Cache vorhanden ist, wird eine Netzwerkanforderung gesendet, um es abzurufen.

Der Servicemitarbeiter aktiviert auch die Push-Benachrichtigungen, die heutzutage auf vielen Websites üblich sind, darunter Facebook, WhatsApp im Internet und Twitter. Wir werden hauptsächlich über die Offline-Funktion sprechen. Diese Anleitung ist spezifisch für Jekyll, der Großteil des Service Worker-Codes kann jedoch allgemein auf jede Website angewendet werden.

Da Jekyll statische Inhalte bereitstellt ( es ist ein statischer Site-Generator, duh! ), wäre unser Service-Worker-Code sehr einfach und leicht zu verstehen.

AUF GEHT'S:

Auf allen relevanten Seiten wird das folgende Skript ausgeführt. Es macht folgende Dinge:

  1. Prüfen, ob die Service Worker API im Browser vorhanden ist und den Service Worker registrieren.
  2. Wenn der Service-Mitarbeiter aktiviert wurde, senden Sie dem Benutzer eine nette kleine Toast-/Chip-Nachricht, dass die Website jetzt bereit ist, offline verwendet zu werden.
 Funktion showOfflineToast() {
  let offlineToast = document.querySelector('.offline-ready');
  offlineToast.classList.add('aktiv');
  setTimeout(Funktion(){ 
    offlineToast.className = offlineToast.className.replace("active", "").trim();
  }, 5500);
}

// (1)
if (navigator.serviceWorker) {
  navigator.serviceWorker.register('/sw.js').then(function(reg) {
      if (!reg.installing) return;
      console.log("[*] ServiceWorker installiert...");

      var worker = reg.installing;

      worker.addEventListener('statechange', function() {
          if (worker.state == 'redundant') {
              console.log('[*] Installation fehlgeschlagen');
          }
          if (worker.state == 'installiert') {
              console.log('[*] Installation erfolgreich!');
          }
          // (2)
          if (worker.state == 'aktiviert' && !navigator.serviceWorker.controller) {
            showOfflineToast();
          }
      });
  });
} 

gdad-s-river.github.io-(iPhone 6)

Sie können dieses Codestück in eine Datei, z. B. serviceWorker.html , innerhalb des Includes -Verzeichnisses Ihres Jekyll-Codes einfügen und es mithilfe von Jekylls flüssiger Templating-Engine in default.html einfügen

 <!DOCTYPE html>
<html>

  {% schließt head.html ein %}

  <Körper>
    {% enthalten header.html %}

    <div class="page-content">
      <div class="Wrapper">
        {{ Inhalt }}
      </div>
    </div>

    {% enthalten footer.html %}

    <!-- Enthält den obigen Code in einem script-Tag-->
    {% umfassen serviceWorker.html %} 

    <div class="offline-ready">Site ist bereit für die Offline-Nutzung</div>
  </body>

</html>

Nun zum eigentlichen Service-Worker-Code, der die Magie bewirkt. Dieser Code befindet sich in sw.js im Stammverzeichnis Ihres Jekyll-Codes.

 //sw.js
---
Layout: null
---

const staticCacheName = "gdad-s-river-static-v61";

console.log("service worker wird installiert");

const filesToCache = [
  "/",
  {% für Seite in site.html_pages %}
    '{{ Seiten-URL }}',
  {% endfor %}
  {% für Post in site.posts %}
    '{{ post.url }}',
  {% endfor %}

  // kann statt manueller Eingaben automatisiert werden
  "/assets/images/bhavri-github-callbacks.png",
  "/assets/images/bhavri-github-issues.png",
  "/assets/images/jakethecake-svg-line-anime.png",
  "/assets/images/svg-animated-mast-text-shapes-tweet.png",
  "css/main.css",
  "/Über/",
  "/index.html"
];

staticCacheName ist die Cache-Version, die jedes Mal aktualisiert werden soll, wenn ich einige Änderungen an den zwischengespeicherten Antworten vornehme (z. B. wenn ich eine Änderung an einer CSS-Datei oder einem Blog-Beitrag vornehme). Und ich definiere gerade, welche Anfragen ich abfangen und in einem Array zwischenspeichern möchte (wird im nächsten Codeausschnitt verwendet).

 //sw.js

self.addEventListener("install", function(e){
  self.skipWaiting();
  e.waitUntil(
    caches.open(staticCacheName).then(function(cache){
      cache.addAll(filesToCache) zurückgeben;
    })
  )
});

self.skipWaiting , bedeutet, dass jedes Mal, wenn sich diese sw.js -Datei ändert, die neuere Version des Service Workers nicht in die Warteschlange gestellt, sondern sofort aktiviert werden sollte (Man könnte nach einer Benutzeraufforderung fragen, um die Seite zu aktualisieren, die eine Nachricht wie Die Webseite wurde aktualisiert/geändert, klicken Sie auf Aktualisieren, um neue Beiträge zu laden oder was auch immer. ), und werfen Sie die ältere Version weg.

java-and-android-square-ad-1

e.waitUntil Zitat von der MDN-Website:

„Die Methode ExtendableEvent.waitUntil() verlängert die Lebensdauer des Ereignisses. Bei Servicemitarbeitern verhindert die Verlängerung der Lebensdauer eines Ereignisses, dass der Browser den Servicemitarbeiter beendet, bevor asynchrone Vorgänge innerhalb des Ereignisses abgeschlossen sind.“

Ich öffne einen Cache namens gdad-s-river-static-v61 , der ein Promise mit meinem Cache-Namen zurückgibt, und dann rufe ich cache.addAll auf (der die Abruf-API im Hintergrund verwendet), der alle Anforderungen in der Array bereitgestellt und zwischengespeichert.

Auf zum nächsten Ausschnitt!

 //sw.js

self.addEventListener("aktivieren", Funktion(e){
  e.waitUntil(
    caches.keys().then(function(cacheNames){
      Rückgabe Promise.all(
        CacheNames.filter(Funktion(CacheName){
          return cacheName.startsWith("gdad-s-river-static-")
            && cacheName != statischerCacheName;
        }).map(Funktion(CacheName){
          cache.delete(cacheName) zurückgeben;
        })
      )ß
    })
  )
});

Wenn der Service Worker aktiviert wird, stelle ich sicher, dass jeder Service Worker, der nicht die neueste Version ist, gelöscht wird. Wenn meine neueste Cache-Version beispielsweise gdad-s-river-static-v61 lautet und jemand bei seinem/ihrem nächsten Besuch immer noch gdad-s-river-static-v58 verwendet , möchte ich, dass sich dieser Client nicht darum kümmert eine Version nach der anderen pumpen, aber diese Version direkt löschen, um die neueste zu installieren.

 //sw.js

self.addEventListener("fetch", function(e){
  e.respondWith(
     caches.match(e.request).then(Funktion(Antwort) {
       Rückantwort || fetch(e.request);
     })
   )
});

Beim Abrufereignis sage ich dem Servicemitarbeiter einfach, wie er auf eine bestimmte gestellte Anfrage antworten soll (da wir die Antwort gebende Macht entführen, arbeiten Servicemitarbeiter nur auf sicheren aka https-Ursprungswebsites). Ich sage ihm, dass er die Anfrage mit den im Browser zwischengespeicherten abgleichen soll, und wenn er diese bestimmte Antwort auf die Anfrage nicht findet, holt er sie über das Netzwerk, andernfalls bedient er sie aus dem Cache.

Tada! Ein Servicemitarbeiter hat den von Jekyll betriebenen Blog offline geschaltet!

ÜBERRASCHUNG! DAS COOLE DING:

Schade: Das würde auf iOS-Geräten nicht funktionieren.

Wenn Sie wie folgt eine manifest.json -Datei der Webanwendung im Stammverzeichnis des Projekts hinzufügen:

 {
  "name": "gdad-s-river",
  "short_name": "gdad-s-river",
  "theme_color": "#2196f3",
  "background_color": "#2196f3",
  "Anzeige": "eigenständig",
  "Zielfernrohr": "/",
  "start_url": "/",
  "Symbole": [
    {
     "src": "assets/images/favicon_images/android-icon-36x36.png",
     "Größen": "36x36",
     "Typ": "Bild\/png",
     "Dichte": "0,75"
    },
    {
     "src": "assets/images/favicon_images/android-icon-48x48.png",
     "Größen": "48x48",
     "Typ": "Bild\/png",
     "Dichte": "1,0"
    },
    {
     "src": "assets/images/favicon_images/android-icon-72x72.png",
     "Größen": "72x72",
     "Typ": "Bild\/png",
     "Dichte": "1,5"
    },
    {
     "src": "assets/images/favicon_images/android-icon-96x96.png",
     "Größen": "96x96",
     "Typ": "Bild\/png",
     "Dichte": "2,0"
    },
    {
     "src": "assets/images/favicon_images/android-icon-144x144.png",
     "Größen": "144x144",
     "Typ": "Bild\/png",
     "Dichte": "3,0"
    },
    {
     "src": "assets/images/favicon_images/android-icon-192x192.png",
     "Größen": "192x192",
     "Typ": "Bild\/png",
     "Dichte": "4,0"
    }
  ]
}

und fügen Sie es in der Datei head.html innerhalb des Head-Tags hinzu,

 <Kopf>
 <!-- einige Sachen -->
	<link rel="manifest" href="/manifest.json">
 <!-- einige Sachen -->
</head>

Beim zweiten Besuch Ihrer Website (innerhalb von 5 Minuten) wird der Benutzer dann aufgefordert, Ihre Website zu Ihrem Startbildschirm hinzuzufügen (um mit einem Symbol angezeigt zu werden, genau wie bei anderen nativen Apps), mit dem Sie genauso interagieren werden eine App.

Screenshot_20170123-232947

RESSOURCEN

  • Einzelheiten zu den Offline-Funktionen und Caching-Strategien von Servicemitarbeitern finden Sie in diesem fantastischen Offline-Kochbuch von Jake Archibald.
  • Ein sehr detaillierter kostenloser Udacity-Kurs über alles, was Sie jemals über Service Worker und IndexDB wissen müssen.

Fanden Sie diesen Artikel im Jekyll Blog interessant und hilfreich? Vergessen Sie nicht, Ihre Ansichten und Ihr Feedback mitzuteilen.

Lesen Sie auch : Ecosia – Die Suchmaschine, die Bäume pflanzt