Lucrătorii de servicii sunt puternici și merită neapărat să învețe. Aceștia vă permit să oferiți un nivel complet nou de experiență utilizatorilor dumneavoastră. Site-ul dvs. se poate încărca instantaneu. Poate funcționa offline. Poate fi instalat ca o aplicație nativă și să se simtă la fel de bine finisat – dar cu raza de acțiune și libertatea web-ului.

Dar lucrătorii de servicii nu seamănă cu nimic din ceea ce majoritatea dintre noi, dezvoltatorii web, suntem obișnuiți. Ei vin cu o curbă de învățare abruptă și o mână de piedici la care trebuie să fiți atenți.

Google Developers și eu am colaborat recent la un proiect-Service Workies-un joc gratuit pentru a înțelege lucrătorii de servicii. În timp ce îl construiam și lucram cu intrările și ieșirile complexe ale lucrătorilor de servicii, m-am lovit de câteva piedici. Ceea ce m-a ajutat cel mai mult a fost să vin cu o mână de metafore descriptive. În această postare vom explora aceste modele mentale și ne vom înfășura creierele în jurul trăsăturilor paradoxale care îi fac pe lucrătorii de servicii atât înșelători, cât și grozavi.

La fel, dar diferit #

În timp ce vă codificați lucrătorul de servicii, multe lucruri vă vor părea familiare. Veți avea ocazia să folosiți noile dvs. caracteristici preferate ale limbajului JavaScript. Ascultați evenimentele ciclului de viață la fel ca în cazul evenimentelor UI. Gestionați fluxul de control cu promisiuni, așa cum v-ați obișnuit.

Dar alte comportamente ale lucrătorului de servicii vă fac să vă zgâriați capul în confuzie. Mai ales atunci când reîmprospătați pagina și nu vedeți modificările de cod aplicate.

Un nou strat #

În mod normal, atunci când construiți un site trebuie să vă gândiți doar la două straturi: clientul și serverul. Lucrătorul de servicii este un strat complet nou care se află la mijloc.

Gândiți-vă la lucrătorul de servicii ca la un fel de extensie de browser – una pe care site-ul dvs. o poate instala în browserul utilizatorului dvs. Odată instalat, lucrătorul de servicii extinde browserul pentru site-ul dvs. cu un strat intermediar puternic. Acest strat al lucrătorului de servicii poate intercepta și gestiona toate solicitările pe care le face site-ul dumneavoastră.

Capacitatea lucrătorului de servicii are propriul său ciclu de viață independent de fila de browser. O simplă reîmprospătare a paginii nu este suficientă pentru a actualiza un lucrător de servicii – la fel cum nu v-ați aștepta ca o reîmprospătare a paginii să actualizeze codul implementat pe un server. Fiecare strat are propriile reguli unice de actualizare.

În jocul Service Workies acoperim numeroasele detalii ale ciclului de viață al lucrătorului de servicii și vă oferim o tonă de practică de lucru cu acesta.

Gândiți-vă la lucrătorul de servicii ca la un nou strat intermediar cu propriul său ciclu de viață și metode de actualizare.

Puternic, dar limitat #

Având un lucrător de servicii pe site-ul dvs. vă oferă beneficii incredibile. Site-ul dvs. poate:

  • funcționa impecabil chiar și atunci când utilizatorul este offline
  • obține îmbunătățiri masive ale performanței prin cache
  • utiliza notificări push
  • fi instalat ca PWA

Cu tot ce pot face lucrătorii de servicii, aceștia sunt limitați prin design. Ei nu pot face nimic sincron sau în același fir de execuție cu site-ul dvs. Deci, asta înseamnă că nu are acces la:

  • localStorage
  • the DOM
  • the window

Veste bună este că există o mână de moduri în care pagina dvs. poate comunica cu lucrătorul său de servicii, inclusiv canale de mesaje directe postMessage, unu-la-unu și canale de difuzare unu-la-mulțime.

Gândiți-vă la lucrătorul dvs. de servicii ca la ceva care trăiește în afara paginii dvs. Puteți vorbi cu el, dar nu poate accesa direct pagina dumneavoastră.

Lungă durată de viață, dar de scurtă durată #

Un lucrător de servicii activ continuă să trăiască chiar și după ce un utilizator părăsește site-ul dumneavoastră sau închide fila. Browserul păstrează acest lucrător de servicii astfel încât să fie pregătit data viitoare când utilizatorul se întoarce pe site-ul dumneavoastră. Înainte ca prima cerere să fie făcută, lucrătorul de servicii are șansa de a o intercepta și de a prelua controlul paginii. Aceasta este ceea ce permite unui site să funcționeze offline – lucrătorul de servicii poate servi o versiune în cache a paginii în sine, chiar dacă utilizatorul nu are conexiune la internet.

În Service Workies vizualizăm acest concept cu Kolohe (un lucrător de servicii prietenos) care interceptează și gestionează cererile.

Stopped #

În ciuda faptului că lucrătorii de servicii par a fi nemuritori, ei pot fi opriți aproape în orice moment. Browserul nu dorește să irosească resurse pe un lucrător de servicii care nu face nimic în prezent. A fi oprit nu este același lucru cu a fi reziliat – lucrătorul de servicii rămâne instalat și activat. Acesta este doar pus la culcare. Data viitoare când este nevoie de el (de exemplu, pentru a gestiona o cerere), browserul îl trezește din nou.

waitUntil #

Din cauza posibilității constante de a fi adormit, lucrătorul dvs. de servicii are nevoie de o modalitate de a anunța browserul când face ceva important și nu are chef să tragă un pui de somn. Aici intervine event.waitUntil(). Această metodă extinde ciclul de viață în care este utilizată, împiedicând-o atât să fie oprită, cât și să treacă la următoarea fază a ciclului său de viață până când suntem pregătiți. Acest lucru ne oferă timp pentru a configura cache-uri, a prelua resurse din rețea etc.

Acest exemplu îi spune browserului că lucrătorul nostru de servicii nu a terminat de instalat până când cache-ul assets nu a fost creat și populat cu imaginea unei săbii:

self.addEventListener("install", event => {
event.waitUntil(
caches.open("assets").then(cache => {
return cache.addAll();
})
);
});

Atenție la starea globală #

Când se întâmplă această pornire/oprire, domeniul global al lucrătorului de servicii este resetat. Așa că aveți grijă să nu folosiți nici o stare globală în lucrătorul dvs. de servicii sau veți fi trist data viitoare când se va trezi din nou și va avea o stare diferită de cea pe care o aștepta.

Considerați acest exemplu care folosește o stare globală:

const favoriteNumber = Math.random();
let hasHandledARequest = false;
self.addEventListener("fetch", event => {
console.log(favoriteNumber);
console.log(hasHandledARequest);
hasHandledARequest = true;
});

La fiecare solicitare acest lucrător de servicii va înregistra un număr – să spunem 0.13981866382421893. Variabila hasHandledARequest se schimbă, de asemenea, în true. Acum, lucrătorul de servicii stă în inactivitate pentru un timp, așa că browserul îl oprește. Data viitoare când există o solicitare, lucrătorul de servicii este necesar din nou, așa că browserul îl trezește. Scriptul său este evaluat din nou. Acum hasHandledARequest este resetat la false, iar favoriteNumber este ceva complet diferit – 0.5907281835659033.

Nu vă puteți baza pe starea stocată într-un lucrător de servicii. De asemenea, crearea de instanțe ale unor lucruri precum Message Channels poate cauza erori: veți obține o instanță complet nouă de fiecare dată când lucrătorul de servicii se oprește/pornește.

Avertisment: Acest impediment este deosebit de important de reținut în timp ce lucrați la codul lucrătorului de servicii, deoarece atunci când Chrome DevTools este deschis, comportamentul de pornire/oprire este dezactivat. Este posibil să nu vedeți nici măcar bug-urile cauzate de faptul că vă bazați pe starea globală până când acestea nu au fost livrate utilizatorilor dumneavoastră.

În Service Workies capitolul 3 vizualizăm lucrătorul nostru de servicii oprit ca pierzând toată culoarea în timp ce așteaptă să fie trezit.

Gândiți-vă la lucrătorul dumneavoastră de servicii ca la un câine biciuit. Este rapid, loial și minunat. Va rămâne alături de dvs. indiferent de situație. Dar în cea mai mare parte vrea doar să doarmă. Tot timpul. Trebuie să-l anunțați când vreți să rămână treaz. Bun câine!

Împreună, dar separat #

Pagina ta poate fi controlată doar de un singur lucrător de servicii la un moment dat. Dar poate avea doi lucrători de servicii instalați în același timp. Atunci când faceți o modificare în codul lucrătorului de servicii și reîmprospătați pagina, de fapt nu editați deloc lucrătorul de servicii. Lucrătorii de servicii sunt imuabili. În schimb, creați unul complet nou. Acest nou lucrător de servicii (să îl numim SW2) se va instala, dar nu se va activa încă. Trebuie să aștepte ca lucrătorul de servicii curent (SW1) să se termine (când utilizatorul dvs. părăsește site-ul dvs.).

Mijloacerea cu cache-urile unui alt lucrător de servicii #

În timp ce se instalează, SW2 poate configura anumite lucruri – de obicei crearea și popularea cache-urilor. Dar atenție: acest nou lucrător de servicii are acces la tot ceea ce are acces lucrătorul de servicii curent. Dacă nu sunteți atenți, noul lucrător de servicii în așteptare poate încurca foarte mult lucrurile pentru lucrătorul de servicii actual. Câteva exemple care v-ar putea cauza probleme:

  • SW2 ar putea șterge un cache pe care SW1 îl folosește în mod activ.
  • SW2 ar putea modifica conținutul unui cache pe care SW1 îl folosește, determinând SW1 să răspundă cu active pe care pagina nu le așteaptă.

Skip skipWaiting #

Un lucrător de servicii poate folosi, de asemenea, metoda riscantă skipWaiting() pentru a prelua controlul paginii imediat ce a terminat de instalat. Aceasta este, în general, o idee proastă, cu excepția cazului în care încercați în mod intenționat să înlocuiți un lucrător de servicii cu erori. Noul lucrător de servicii ar putea folosi resurse actualizate pe care pagina curentă nu le așteaptă, ceea ce duce la erori și erori.

Începeți curate #

Modalitatea de a preveni ca lucrătorii de servicii să se lovească între ei este să vă asigurați că folosesc cache-uri diferite. Cel mai simplu mod de a realiza acest lucru este de a versifica numele de cache pe care le folosesc.

const version = 1;
const assetCacheName = `assets-${version}`;
self.addEventListener("install", event => {
caches.open(assetCacheName).then(cache => {
// confidently do stuff with your very own cache
});
});

Când implementați un nou lucrător de servicii, veți schimba version astfel încât acesta să facă ceea ce are nevoie cu un cache complet separat de cel al lucrătorului de servicii anterior.

Sfârșește curat #

După ce lucrătorul dvs. de servicii ajunge la starea activated, știți că a preluat controlul, iar lucrătorul de servicii anterior este redundant (de ex, nu mai este necesar). În acest moment, este important să curățați după vechiul lucrător de servicii. Nu numai că respectă limitele de stocare în memoria cache a utilizatorilor dumneavoastră, dar poate, de asemenea, să prevină apariția unor erori neintenționate.

Metoda caches.match() este o scurtătură des folosită pentru a prelua un element din orice cache în care există o potrivire. Dar aceasta parcurge cache-urile în ordinea în care au fost create. Deci, să spunem că aveți două versiuni ale unui fișier de script app.js în două cache-uri diferite – assets-1 și assets-2. Pagina dvs. așteaptă scriptul mai nou care este stocat în assets-2. Dar dacă nu ați șters vechiul cache, caches.match('app.js') o va returna pe cea veche din assets-1 și, cel mai probabil, vă va strica site-ul.

Tot ce este nevoie pentru a face curățenie după lucrătorii de servicii anteriori este să ștergeți orice memorie cache de care noul lucrător de servicii nu are nevoie:

const version = 2;
const assetCacheName = `assets-${version}`;
self.addEventListener("activate", event => {
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
if (cacheName !== assetCacheName){
return caches.delete(cacheName);
}
});
);
});
);
});

Pentru a preveni ca lucrătorii de servicii să se lovească între ei este nevoie de puțină muncă și disciplină, dar merită osteneala.

Gândiți-vă la combinația dintre lucrătorul de servicii și site-ul dvs. ca la o aplicație instalabilă. Fiecare versiune ar trebui să funcționeze. Fiecare versiune ar trebui să fie separată de celelalte. Imaginați-vă cât de eronat ar fi un joc dacă dezvoltatorul ar lansa din greșeală un patch care folosește o nouă logică de joc, dar active învechite. Te-ai înfuria pe forumuri atât de repede! Păstrați versiunile aplicației dvs. ordonate & curate.

Starea de spirit a lucrătorului de servicii #

Prinderea unei stări de spirit corecte în timp ce vă gândiți la lucrătorii de servicii vă va ajuta să o construiți pe a dvs. cu încredere. Odată ce le veți prinde gustul, veți putea crea experiențe incredibile pentru utilizatorii dumneavoastră.

Dacă doriți să înțelegeți toate acestea jucând un joc, atunci aveți noroc! Mergeți să jucați Service Workies unde veți învăța căile lucrătorului de servicii pentru a ucide bestiile offline.

Ultima actualizare: Jun 4, 2019 Îmbunătățiți articolul

.

Lasă un răspuns

Adresa ta de email nu va fi publicată.