A szolgáltatói gondolkodásmód erős, és feltétlenül érdemes megtanulni. Lehetővé teszik, hogy teljesen új szintű élményt nyújtson a felhasználóknak. Az oldalad azonnal betöltődhet. Offline is működhet. Telepíthető natív alkalmazásként, és ugyanolyan kifinomultnak tűnhet – de a web elérhetőségével és szabadságával.

A szervizmunkások azonban nem hasonlítanak semmihez, amihez a legtöbb webfejlesztő hozzászokott. Meredek tanulási görbével és egy maroknyi bökkenővel járnak, amire oda kell figyelni.

A Google Developers és én nemrég közösen dolgoztunk egy Service Workies nevű projekten – egy ingyenes játék a szervizmunkások megértéséhez. Miközben építettem és dolgoztam a szolgáltatási munkások összetett belső és külsőségeivel, belefutottam néhány bökkenőbe. Ami a legtöbbet segített, az az volt, hogy kitaláltam egy maroknyi ábrázoló metaforát. Ebben a bejegyzésben felfedezzük ezeket a mentális modelleket, és körbejárjuk az agyunkat azokon a paradox vonásokon, amelyek egyszerre teszik trükkössé és fantasztikusvá a szervizmunkásokat.

Egyforma, de más #

A szervizmunkás kódolása közben sok minden ismerősnek fog tűnni. Használhatod a kedvenc új JavaScript nyelvi funkcióidat. Figyelsz az életciklus eseményeire, akárcsak a felhasználói felület eseményeinél. A vezérlésáramlást ígéretekkel kezeled, ahogy megszoktad.

De más service worker viselkedés miatt zavartan vakargatod a fejed. Különösen akkor, amikor frissíted az oldalt, és nem látod, hogy a kódod módosításait alkalmazzák.

Egy új réteg #

Normális esetben egy webhely építése során csak két rétegre kell gondolnod: a kliensre és a kiszolgálóra. A szervizmunkás egy vadonatúj réteg, amely középen helyezkedik el.

Gondolj úgy a szervizmunkásodra, mint egyfajta böngészőbővítményre – olyanra, amelyet a webhelyed telepíthet a felhasználó böngészőjébe. A telepítést követően a szervizmunkás egy nagy teljesítményű középső réteggel bővíti ki a webhely böngészőjét. Ez a szervizmunkás réteg képes elfogni és kezelni az összes kérést, amelyet a webhelye tesz.

A szervizmunkás rétegnek saját, a böngésző lapjától független életciklusa van. Egy egyszerű oldalfrissítés nem elegendő a szervizmunkás frissítéséhez – ahogyan a kiszolgálón telepített kód frissítését sem várná el egy oldalfrissítéstől. Minden rétegnek saját, egyedi szabályai vannak a frissítésre.

A Service Workies játékban a service worker életciklusának számos részletével foglalkozunk, és rengeteg gyakorlatot adunk a vele való munkához.

Gondolj úgy a service workerre, mint egy új középső rétegre, saját életciklussal és frissítési módszerekkel.

Elképesztő, de korlátozott #

Hihetetlen előnyökkel jár, ha egy service worker van a webhelyeden. Az oldalad:

  • hibátlanul működhet akkor is, ha a felhasználó offline
  • a gyorsítótárazással hatalmas teljesítményjavulást érhet el
  • push értesítések használata
  • PWA-ként telepíthető

Mindenre képesek a szervizmunkások, de eleve korlátozottak. Semmit sem tudnak szinkronban vagy a webhelyeddel azonos szálban csinálni. Ez tehát azt jelenti, hogy nem férhetnek hozzá:

  • localStorage
  • the DOM
  • the window

A jó hír az, hogy van egy maroknyi módja annak, hogy az oldalad kommunikáljon a szervizmunkással, beleértve a közvetlen postMessage, egy-egy üzenetcsatornákat és egy-másik broadcast csatornákat.

Gondolj úgy a szervizmunkásodra, mint valami olyanra, ami az oldaladon kívül él. Beszélhetsz vele, de nem tud közvetlenül hozzáférni az oldaladhoz.

Hosszú életű, de rövid életű #

Az aktív szolgáltatásmunkás még akkor is tovább él, ha a felhasználó elhagyja az oldaladat vagy bezárja a lapot. A böngésző megtartja ezt a szervizmunkást, hogy készen álljon, amikor a felhasználó legközelebb visszatér az oldaladra. Mielőtt a legelső kérés megtörténne, a szervizmunkás lehetőséget kap arra, hogy elfogja azt, és átvegye az oldal irányítását. Ez teszi lehetővé, hogy egy webhely offline működjön – a szervizmunkás képes kiszolgálni magának az oldalnak egy gyorsítótárazott változatát, még akkor is, ha a felhasználónak nincs kapcsolata az internettel.

A szervizmunkásokban ezt a koncepciót Kolohe (egy barátságos szervizmunkás) segítségével szemléltetjük, aki elfogja és kezeli a kéréseket.

Stop #

A szervizmunkások annak ellenére, hogy halhatatlannak tűnnek, szinte bármikor leállíthatók. A böngésző nem akar erőforrásokat pazarolni egy olyan szervizmunkásra, amely éppen nem csinál semmit. A leállítás nem ugyanaz, mint a megszüntetés – a szervizmunkás továbbra is telepítve és aktiválva marad. Csak alvó üzemmódba kerül. Amikor legközelebb szükség lesz rá (pl. egy kérés kezeléséhez), a böngésző felébreszti.

waitUntil #

Az alvó állapotba helyezés állandó lehetősége miatt a szervizmunkásodnak tudnia kell a böngészővel, hogy mikor csinál valami fontosat, és mikor nincs kedve szundikálni. Itt jön a képbe a event.waitUntil(). Ez a metódus meghosszabbítja az életciklusát, amelyben használják, megakadályozva mind a leállítást, mind az életciklus következő fázisába való továbblépést, amíg készen nem állunk. Ez időt ad nekünk a gyorsítótárak beállítására, erőforrások lehívására a hálózatról, stb.

Ez a példa azt mondja a böngészőnek, hogy a szervizmunkásunk nem fejezi be a telepítést, amíg a assets gyorsítótár nem jön létre és nem töltődik fel egy kard képével:

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

Vigyázz a globális állapotra #

Amikor ez a start/stop történik, a szervizmunkás globális hatókörét visszaállítja. Tehát vigyázz, hogy ne használj semmilyen globális állapotot a szervizmunkásodban, különben szomorú leszel, amikor legközelebb újra felébred, és más állapota van, mint amire számított.

Nézzük ezt a példát, amely globális állapotot használ:

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

Ez a szervizmunkás minden egyes kérésnél naplózni fog egy számot – mondjuk 0.13981866382421893. A hasHandledARequest változó is true-re változik. Most a szervizmunkás egy darabig tétlenül ül, ezért a böngésző leállítja. A következő kéréskor ismét szükség van a szervizmunkásra, ezért a böngésző felébreszti. A szkriptje ismét kiértékelésre kerül. Most a hasHandledARequest visszaáll false-re, és a favoriteNumber valami teljesen más –0.5907281835659033.

Egy szervizmunkásnál nem lehet a tárolt állapotra támaszkodni. Emellett az olyan dolgok példányainak létrehozása, mint a Message Channels, hibákat okozhat: egy teljesen új példányt kapsz minden alkalommal, amikor a szervizmunkás leáll/indul.

Figyelmeztetés: Ezt a bökkenőt különösen fontos szem előtt tartani, amikor a szervizmunkás kódján dolgozik, mert amikor a Chrome DevTools nyitva van, az indítási/leállítási viselkedés le van tiltva. Előfordulhat, hogy a globális állapotra való támaszkodás által okozott hibákat nem is látod, amíg azok el nem jutnak a felhasználóidhoz.

A Service Workies 3. fejezetében a leállított service workerünket úgy képzeljük el, hogy minden színét elveszíti, amíg arra vár, hogy felébredjen.

Gondolj a service workeredre úgy, mint egy ostoros kutyára. Gyors, hűséges és félelmetes. Bármi történjen is, kitart melletted. De leginkább csak aludni akar. Állandóan. Tudatnod kell vele, hogy mikor akarod, hogy ébren maradjon. Jó kutya!

Együtt, de külön #

Az oldaladat egyszerre csak egy szervizmunkás irányíthatja. De egyszerre két szervizmunkás is telepíthető rá. Amikor módosítod a szervizmunkás kódját, és frissíted az oldalt, valójában egyáltalán nem szerkeszted a szervizmunkásodat. A szervizmunkások megváltoztathatatlanok. Ehelyett egy teljesen újat készítesz. Ez az új szervizmunkás (nevezzük SW2-nek) települ, de még nem aktiválódik. Meg kell várnia, hogy a jelenlegi szervizmunkás (SW1) megszűnjön (amikor a felhasználó elhagyja a webhelyet).

Más szervizmunkás cache-jeivel való foglalkozás #

A telepítés során az SW2 beállíthat dolgokat – általában létrehozza és feltölti a cache-eket. De figyelem: ez az új szervizmunkás hozzáférhet mindenhez, amihez a jelenlegi szervizmunkás hozzáfér. Ha nem vigyázol, az új várakozó szervizmunkás nagyon összekuszálhatja a jelenlegi szervizmunkás dolgait. Néhány példa, ami gondot okozhat:

  • SW2 törölhet egy olyan gyorsítótárat, amelyet az SW1 aktívan használ.
  • SW2 szerkesztheti az SW1 által használt gyorsítótár tartalmát, aminek következtében az SW1 olyan eszközökkel válaszol, amelyekre az oldal nem számít.

Skip skipWaiting #

A szervizmunkás a kockázatos skipWaiting() módszerrel is átveheti az oldal irányítását, amint befejezte a telepítést. Ez általában rossz ötlet, hacsak nem akarsz szándékosan egy hibás szervizmunkást helyettesíteni. Az új szervizmunkás olyan frissített erőforrásokat használhat, amelyekre az aktuális oldal nem számít, ami hibákhoz és hibákhoz vezethet.

Start clean #

A módja annak, hogy megakadályozzuk, hogy a szervizmunkások egymást elkapkodják, ha gondoskodunk arról, hogy különböző gyorsítótárakat használjanak. Ennek legegyszerűbb módja, ha az általuk használt gyorsítótárnevek verziója.

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

Amikor egy új szervizmunkást telepítesz, a version-t úgy bumpolod, hogy az előző szervizmunkástól teljesen különálló gyorsítótárral csinálja, amit kell.

End clean #

Amikor a szervizmunkásod eléri a activated állapotot, tudod, hogy átvette az irányítást, és az előző szervizmunkás felesleges (azaz, már nincs rá szükség). Ekkor fontos, hogy eltakarítsuk a régi szervizmunkás után. Ez nem csak a felhasználók gyorsítótár-tárolási korlátait tartja tiszteletben, de a nem szándékos hibákat is megelőzheti.

A caches.match() módszer egy gyakran használt rövidítés egy elem lekérdezésére bármely olyan gyorsítótárból, ahol van egyezés. De ez a módszer a létrehozásuk sorrendjében végigmegy a gyorsítótárakon. Tegyük fel, hogy egy app.js szkriptfájl két verziója van két különböző gyorsítótárban – assets-1 és assets-2. Az oldalad a assets-2-ben tárolt újabb szkriptet várja. De ha nem törölted a régi gyorsítótárat, akkor a caches.match('app.js') a assets-1-ből a régit fogja visszaadni, és valószínűleg tönkreteszi az oldaladat.

A korábbi szervizmunkások utáni takarításhoz mindössze annyi szükséges, hogy töröljön minden olyan gyorsítótárat, amelyre az új szervizmunkásnak nincs szüksége:

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);
}
});
);
});
);
});

A szervizmunkások egymás eltiprásának megakadályozása egy kis munkát és fegyelmet igényel, de megéri a fáradságot.

Gondoljon úgy a szervizmunkás és a webhelye kombinációjára, mint egy telepíthető alkalmazásra. Mindegyik verziónak működnie kell. Minden verziónak különállónak kell lennie a többitől. Képzeld el, milyen hibás lenne egy játék, ha a fejlesztő véletlenül kiadna egy olyan javítást, amely új játéklogikát, de elavult eszközöket használ. Olyan gyorsan tombolnál a fórumokon! Tartsd rendben az alkalmazásverzióidat & tisztán.

Szolgálati munkások gondolkodásmódja #

A megfelelő gondolkodásmódba helyezkedve, miközben a szolgálati munkásokról gondolkodsz, segíteni fog, hogy magabiztosan építsd fel a tiédet. Ha egyszer elsajátítod őket, hihetetlen élményeket tudsz majd létrehozni a felhasználóid számára.

Ha mindezt egy játékon keresztül szeretnéd megérteni, akkor szerencséd van! Menj és játssz a Service Workies játékkal, ahol megtanulhatod a szervizmunkások módját, hogy megölhesd az offline fenevadakat.

Utolsó frissítés: Június 4, 2019 Cikk javítása

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.