Cum să obțineți un blog Jekyll să lucreze offline folosind lucrătorii de servicii

Publicat: 2017-01-26

Bytes scurti: Știați că , odată cu apariția lucrătorilor de servicii, se poate începe să facă site-urile web să funcționeze offline! Astfel de aplicații web se numesc PWA (Progressive Web Apps). În această instrucțiune, vă voi ajuta să folosiți un lucrător de service pentru a face ca un blog/site web bazat pe Jekyll să funcționeze offline și câteva lucruri interesante care vin cu el.

(NOTĂ : Fragmentele de cod din articol sunt preluate din depozitul de cod al blogului meu. Poate fi trimis dacă este necesar. Dacă sunteți nou la Jekyll, puteți citi articolul din seria 3 despre trucuri CSS.)

FUNDAL

Mai devreme, a existat o aplicație cache bazată pe fișiere YAML yuk, care era de natură foarte codificată și nu putea fi folosită pentru a stoca în cache activele și paginile web în mod dinamic. Intrați, lucrători de service. API Javascript simplu, bazat pe evenimente, pentru a realiza memorarea în cache dinamică a lucrătorilor de servicii pentru a stoca active, astfel încât acestea să poată fi utilizate pentru a servi paginile web atunci când nu există rețea.

Lucrătorii de service au aterizat în Chrome Canary în 2014, dar specificațiile acesteia sunt încă revizuite/adăugate și proiectate. În 2015 și 2016, echipa Google Chrome a răspândit vestea acestei noi tehnologii în browsere. Doar Apple nu a acceptat acest lucru (chiar la momentul scrierii acestui articol) pe dispozitivele lor (din motive necunoscute) [De asemenea, nu participă activ la nicio discuție despre specificații despre lucrătorii din service].

Ce este un lucrător de servicii? Practic, este un lucrător web pe steroizi. O caracteristică a unui lucrător web este că toate sarcinile unui lucrător web rulează separat (asincron) de firul principal de execuție JavaScript (bucla de evenimente). Această caracteristică ajută la executarea sarcinilor care necesită multă memorie CPU sau memorie, de exemplu, calcule complicate, fără a compromite performanța interfeței dvs. de utilizator a aplicației web.

Service Worker ne permite să memorăm în cache (stocare pentru o perioadă lungă de timp) active, cum ar fi JavaScript, CSS, HTML, imagini, fișiere cu fonturi în memoria cache a lucrătorului de service al browserului, astfel încât data viitoare când utilizatorul încarcă pagina respectivă, aceasta este încărcată aproape instantaneu . Și, de asemenea, deoarece în această strategie de stocare în cache, browserul caută disponibilitatea activelor mai întâi din cache-ul lucrătorului de service, pagina web este servită chiar și atunci când unul este offline! Dacă vreun activ nu este acolo în cache, atunci este trimisă o solicitare de rețea pentru a-l prelua.

Lucrătorul de service activează, de asemenea, notificările push care sunt comune pentru multe site-uri web în zilele noastre, inclusiv Facebook, Whatsapp pe web și Twitter. Vom vorbi în primul rând despre funcția offline. Această instrucțiune este specifică Jekyll, cu toate acestea, cea mai mare parte a codului de lucrător al serviciului poate fi aplicată în general oricărui site web.

Deoarece Jekyll servește conținut static ( este un generator de site static, nu! ), codul nostru de lucrător al serviciului ar fi foarte simplu și ușor de înțeles.

SA MERGEM:

Pe toate paginile relevante, următoarea bucată de script este executată. Face următoarele lucruri:

  1. Verificarea existenței API-ului service worker în browser și înregistrarea service worker-ului.
  2. Când lucrătorul de service a fost activat, trimiteți utilizatorului un mesaj mic și drăguț că site-ul web este gata pentru a fi folosit offline acum.
 funcția showOfflineToast() {
  let offlineToast = document.querySelector('.offline-ready');
  offlineToast.classList.add('activ');
  setTimeout(funcție(){ 
    offlineToast.className = offlineToast.className.replace("activ", "").trim();
  }, 5500);
}

// (1)
dacă (navigator.serviceWorker) {
  navigator.serviceWorker.register('/sw.js').then(function(reg) {
      dacă (!reg.installing) returnează;
      console.log("[*] ServiceWorker se instalează...");

      var worker = reg.installing;

      worker.addEventListener('statechange', function() {
          if (worker.state == 'redundant') {
              console.log('[*] Instalarea eșuată');
          }
          if (worker.state == 'instalat') {
              console.log('[*] Instalare reușită!');
          }
          // (2)
          dacă (worker.state == „activat” && !navigator.serviceWorker.controller) {
            showOfflineToast();
          }
      });
  });
} 

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

Puteți adăuga această bucată de cod într-un fișier, cum ar fi serviceWorker.html , în directorul includes al codului dvs. Jekyll și să o includeți în default.html folosind motorul de șabloane lichide al lui Jekyll

 <!DOCTYPE html>
<html>

  {% include head.html %}

  <corp>
    {% include header.html %}

    <div class="page-content">
      <div class="wrapper">
        {{ continut }}
      </div>
    </div>

    {% include footer.html %}

    <!-- Conține codul de mai sus într-o etichetă de script-->
    {% include serviceWorker.html %} 

    <div class="offline-ready">Site-ul este gata pentru utilizare offline</div>
  </corp>

</html>

Acum să trecem la codul de serviciu real care face magia. Acest cod se află în sw.js la rădăcina codului dumneavoastră Jekyll.

 //sw.js
---
aspect: nul
---

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

console.log("se instalează serviciul lucrător");

const filesToCache = [
  „/”,
  {% pentru pagina din site.html_pages %}
    „{{ page.url }}”,
  {% endfor %}
  {% pentru postare în site.posts %}
    „{{ post.url }}”,
  {% endfor %}

  // pot fi automate mai degrabă decât intrări manuale
  „/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”,
  "/despre/",
  „/index.html”
];

staticCacheName este versiunea cache care urmează să fie actualizată de fiecare dată când fac unele modificări la răspunsurile din cache (de exemplu, fac o schimbare într-un fișier CSS sau într-o postare de blog). Și, doar definesc ce solicitări vreau să interceptez și să memorez în cache într-o matrice (folosită în următorul fragment).

 //sw.js

self.addEventListener(„instalare”, funcția(e){
  self.skipWaiting();
  e.waitUntil(
    caches.open(staticCacheName).then(funcție(cache){
      return cache.addAll(filesToCache);
    })
  )
});

self.skipWaiting , înseamnă că de fiecare dată când acest fișier sw.js se modifică, versiunea mai nouă a lucrătorului de servicii nu ar trebui să fie pusă în coadă, ci să fie activată imediat (se poate cere promptul utilizatorului pentru a reîmprospăta pagina, dând un mesaj precum Pagina web a fost actualizată/modificată, faceți clic pe Reîmprospătare pentru a încărca postări noi sau orice altceva. ), aruncând versiunea mai veche.

java-și-android-square-ad-1

e.waitUntil citarea de pe site-ul MDN:

„Metoda ExtendableEvent.waitUntil() extinde durata de viață a evenimentului. În cazul lucrătorilor de servicii, prelungirea duratei de viață a unui eveniment împiedică browserul să oprească lucratorul de service înainte ca operațiunile asincrone din cadrul evenimentului să se fi încheiat.”

Deschid un cache numit gdad-s-river-static-v61 , care returnează o promisiune cu numele meu cache, apoi apel cache.addAll (care folosește API-ul fetch în fundal), care preia toate cererile din matrice furnizată și le pune în cache.

Trecem la următorul fragment!

 //sw.js

self.addEventListener(„activare”, funcția(e){
  e.waitUntil(
    caches.keys().then(function(cacheNames){
      returnează Promise.all(
        cacheNames.filter(function(cacheName){
          return cacheName.startsWith("gdad-s-river-static-")
            && cacheName != staticCacheName;
        }).map(function(cacheName){
          return cache.delete(cacheName);
        })
      )ß
    })
  )
});

Când lucrătorul de service se activează, mă asigur că, orice lucrător de service care nu este cea mai recentă versiune este șters. De exemplu, dacă cea mai recentă versiune a mea cache este să spunem gdad-s-river-static-v61 , iar cineva este încă pe gdad-s-river-static-v58 , la următoarea sa vizită, vreau ca clientului să nu-i pese de pompând câte o versiune, dar ștergeți imediat acea versiune pentru a o instala pe cea mai recentă.

 //sw.js

self.addEventListener(„preluare”, funcția(e){
  e.respondWith(
     caches.match(e.request).then(funcție(răspuns) {
       returnează răspuns || fetch(e.request);
     })
   )
});

În evenimentul de preluare, îi spun pur și simplu lucrătorului de service cum să răspundă la o anumită solicitare făcută (din moment ce deturnăm răspunsul dând putere, lucrătorii de service lucrează doar pe site-uri web de origine https securizate). Îi spun să potrivească cererea cu cele stocate în cache în browser și, dacă nu găsește acel răspuns anume la cerere, îl preia prin rețea, altfel îl servește din cache.

Tada! Lucrătorul de service a creat blogul cu motor Jekyll offline!

SURPRINDE! Lucrul tare:

Păcat: acest lucru nu ar funcționa pe dispozitivele iOS.

Dacă adăugați un fișier manifest.json de aplicație web la rădăcina proiectului, astfel:

 {
  „nume”: „gdad-s-river”,
  "short_name": "gdad-s-river",
  "theme_color": "#2196f3",
  "background_color": "#2196f3",
  "display": "autonom",
  „Scope”: „/”,
  "start_url": "/",
  „icoane”: [
    {
     „src”: „assets/images/favicon_images/android-icon-36x36.png”,
     "dimensiuni": "36x36",
     "type": "imagine\/png",
     "densitate": "0,75"
    },
    {
     „src”: „assets/images/favicon_images/android-icon-48x48.png”,
     "dimensiuni": "48x48",
     "type": "imagine\/png",
     „densitate”: „1,0”
    },
    {
     „src”: „assets/images/favicon_images/android-icon-72x72.png”,
     "dimensiuni": "72x72",
     "type": "imagine\/png",
     „densitate”: „1,5”
    },
    {
     „src”: „assets/images/favicon_images/android-icon-96x96.png”,
     "dimensiuni": "96x96",
     "type": "imagine\/png",
     „densitate”: „2,0”
    },
    {
     „src”: „assets/images/favicon_images/android-icon-144x144.png”,
     "dimensiuni": "144x144",
     "type": "imagine\/png",
     „densitate”: „3,0”
    },
    {
     „src”: „assets/images/favicon_images/android-icon-192x192.png”,
     "dimensiuni": "192x192",
     "type": "imagine\/png",
     „densitate”: „4,0”
    }
  ]
}

și adăugați-l în fișierul head.html din interiorul etichetei head,

 <cap>
 <!-- niște chestii -->
	<link rel="manifest" href="/manifest.json">
 <!-- niște chestii -->
</cap>

Apoi, la a doua vizită a site-ului dvs. web (în decurs de 5 minute), va solicita utilizatorului să vă adauge site-ul pe ecranul dvs. de pornire (pentru a locui cu o pictogramă, la fel ca alte aplicații native), cu care veți fi implicat la fel ca o aplicatie.

Captură de ecran_20170123-232947

RESURSE

  • Detalii despre funcțiile offline ale lucrătorului de servicii și strategiile de stocare în cache pot fi găsite în cartea de bucate offline a acestui minunat Jake Archibald.
  • Un curs Udacity gratuit foarte detaliat despre tot ce ai nevoie să știi despre lucrătorii de service și IndexDB.

Ți s-a părut interesant și util acest articol de pe Jekyll Blog? Nu uitați să vă împărtășiți opiniile și feedback-ul.

Citește și : Ecosia — Motorul de căutare care plantează copaci