Palvelutyöntekijät ovat voimakkaita ja ehdottomasti oppimisen arvoisia. Niiden avulla voit tarjota käyttäjillesi aivan uudenlaisen kokemuksen. Sivustosi voi latautua välittömästi. Se voi toimia offline-tilassa. Se voidaan asentaa natiivina sovelluksena, ja se voi tuntua aivan yhtä kiillotetulta – mutta webin ulottuvuudella ja vapaudella.

Mutta palvelutyöläiset eivät ole mitään sellaista, mihin useimmat meistä web-kehittäjistä ovat tottuneet. Niihin liittyy jyrkkä oppimiskäyrä ja kourallinen sudenkuoppia, joita on varottava.

Google Developers ja minä teimme hiljattain yhteistyötä Service Workies -projektin parissa, joka on ilmainen peli palvelutyöntekijöiden ymmärtämiseksi. Rakentaessani sitä ja työskennellessäni palvelutyöntekijöiden monimutkaisten yksityiskohtien parissa törmäsin muutamaan sudenkuoppaan. Eniten minua auttoi se, että keksin kourallisen kuvaavia metaforia. Tässä postauksessa tutkimme näitä mentaalimalleja ja kietaamme aivomme niiden paradoksaalisten piirteiden ympärille, jotka tekevät palvelutyöntekijöistä sekä hankalia että mahtavia.

Sama, mutta erilainen #

Koodatessasi palvelutyöntekijääsi monet asiat tuntuvat tutuilta. Pääset käyttämään suosikkisi uusia JavaScript-kielen ominaisuuksia. Kuuntelet elinkaaritapahtumia aivan kuten UI-tapahtumia. Hallitset kontrollin kulkua lupauksilla kuten olet tottunut.

Mutta eräät muut palvelutyöläisen käyttäytymistavat saavat sinut raapimaan päätäsi hämmentyneenä. Varsinkin, kun päivität sivun etkä näe, että koodimuutoksesi otetaan käyttöön.

Uusi kerros #

Normaalisti sivustoa rakentaessasi sinun on ajateltava vain kahta kerrosta: asiakasta ja palvelinta. Palvelutyöntekijä on aivan uusi kerros, joka sijoittuu niiden väliin.

Ajattele palvelutyöntekijää eräänlaisena selainlaajennuksena – sellaisena, jonka sivustosi voi asentaa käyttäjän selaimeen. Kun palvelutyöntekijä on asennettu, se laajentaa sivustosi selainta tehokkaalla välikerroksella. Tämä palvelutyökerros voi siepata ja käsitellä kaikki sivustosi tekemät pyynnöt.

Palvelutyökerroksella on oma elinkaarensa, joka on riippumaton selaimen välilehdestä. Pelkkä sivun päivitys ei riitä päivittämään palvelutyöntekijää – aivan kuten et odottaisi sivun päivityksen päivittävän palvelimelle asennettua koodia. Kullakin kerroksella on omat ainutlaatuiset säännöt päivittämistä varten.

Palvelutyöntekijä-pelissä käsittelemme palvelutyöntekijän elinkaaren monia yksityiskohtia ja annamme sinulle valtavasti harjoitusta sen kanssa työskentelyyn.

Ajattele palvelutyöntekijääsi uutena välikerroksena, jolla on oma elinkaarensa ja omat päivitysmenetelmänsä.

Voimakas, mutta rajallinen #

Palvelutyöntekijän käyttäminen sivustossasi antaa uskomattomia etuja. Sivustosi voi:

  • toimia moitteettomasti silloinkin, kun käyttäjä on offline-tilassa
  • saada massiivisia suorituskykyparannuksia välimuistitallennuksen avulla
  • käyttää push-ilmoituksia
  • asennettuna PWA:ksi

Niin paljon kuin palvelutyöläiset voivatkin tehdä, ne ovat rakenteeltaan rajoitettuja. Ne eivät voi tehdä mitään synkronista tai samassa säikeessä sivustosi kanssa. Tämä tarkoittaa siis sitä, ettei heillä ole pääsyä:

  • localStorage
  • DOM
  • Ikkunaan

Hyvä uutinen on se, että on olemassa kourallinen tapoja, joilla sivusi voi kommunikoida palvelutyöntekijänsä kanssa, mukaan lukien suorat postMessage, yhdestä yhteen -viestikanavat ja yhdestä moniin -lähetyskanavat.

Ajattele palvelutyöntekijääsi joksikin, joka asuu sivusi ulkopuolella. Voit puhua sille, mutta se ei pääse suoraan sivullesi.

Pitkäkestoinen, mutta lyhytikäinen #

Aktiivinen palvelutyöntekijä jatkaa elämäänsä silloinkin, kun käyttäjä poistuu sivustoltasi tai sulkee välilehden. Selain pitää tätä palvelutyöntekijää yllä, jotta se on valmiina, kun käyttäjä seuraavan kerran palaa sivustollesi. Ennen kuin ensimmäinen pyyntö tehdään, palvelutyöntekijä saa tilaisuuden siepata sen ja ottaa sivun hallintaansa. Tämän ansiosta sivusto voi toimia offline-tilassa – palvelutyöntekijä voi palvella itse sivun välimuistiin tallennettua versiota, vaikka käyttäjällä ei olisikaan yhteyttä internetiin.

Palvelutyöntekijöissä visualisoimme tämän käsitteen Kolohella (ystävällinen palvelutyöntekijä), joka sieppaa pyynnöt ja käsittelee ne.

Pysäytetty #

Palvelutyöntekijät vaikuttavat kuolemattomilta, mutta ne voidaan pysäyttää melkein milloin tahansa. Selain ei halua tuhlata resursseja palvelutyöntekijään, joka ei tällä hetkellä tee mitään. Pysäyttäminen ei ole sama asia kuin lopettaminen – palvelutyöntekijä pysyy asennettuna ja aktivoituna. Se vain asetetaan lepotilaan. Seuraavan kerran, kun sitä tarvitaan (esim. käsittelemään pyyntöä), selain herättää sen uudelleen.

waitUntil #

Koska on jatkuva mahdollisuus joutua lepotilaan, palveluntyöläinen tarvitsee keinon ilmoittaa selaimelle, kun se tekee jotain tärkeää eikä halua ottaa torkkuja. Tässä kohtaa event.waitUntil() tulee kuvaan mukaan. Tämä metodi pidentää elinkaarta, jossa sitä käytetään, ja estää sitä sekä pysähtymästä että siirtymästä elinkaarensa seuraavaan vaiheeseen, kunnes olemme valmiita. Tämä antaa meille aikaa perustaa välimuistit, hakea resursseja verkosta jne.

Tämä esimerkki kertoo selaimelle, että palveluntyöläisemme ei ole valmis asentamaan ennen kuin assets välimuisti on luotu ja täytetty miekan kuvalla:

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

Varokaa globaalia tilaa #

Kun tämä käynnistys/pysäytys tapahtuu, palveluntyöläisemme globaali laajuus nollataan. Ole siis varovainen, ettet käytä mitään globaalia tilaa palvelutyöntekijässäsi tai olet surullinen, kun se seuraavan kerran herää takaisin ja sillä on eri tila kuin mitä se odotti.

Harkitse tätä esimerkkiä, joka käyttää globaalia tilaa:

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

Jokaiseen pyyntöön tämä palvelutyöntekijä kirjaa numeron – sanotaan vaikka 0.13981866382421893. Muuttuja hasHandledARequest muuttuu myös muuttujaksi true. Nyt palvelutyöntekijä istuu hetken aikaa toimettomana, joten selain pysäyttää sen. Kun seuraavan kerran tulee pyyntö, palvelutyöntekijää tarvitaan taas, joten selain herättää sen. Sen skripti arvioidaan uudelleen. Nyt hasHandledARequest on nollattu false:ksi, ja favoriteNumber on jotain aivan muuta – 0.5907281835659033.

Palvelutyöntekijässä ei voi luottaa tallennettuun tilaan. Myös instanssien luominen esimerkiksi viestikanavista voi aiheuttaa vikoja: saat aivan uuden instanssin joka kerta, kun palvelutyöntekijä pysähtyy/käynnistyy.

Varoitus: Tämä pulma on erityisen tärkeää pitää mielessä, kun työstät service worker -koodia, sillä kun Chrome DevTools on auki, käynnistys/pysäytyskäyttäytyminen ei ole käytössä. Et välttämättä edes huomaa globaaliin tilaan luottamisesta johtuvia vikoja ennen kuin ne on toimitettu käyttäjille.

Palvelutyöntekijöiden luvussa 3 visualisoimme pysähtyneen palvelutyöntekijämme menettävän kaikki värit odottaessaan herättämistä.

Ajatella palvelutyöntekijääsi whippet-koirana. Se on nopea, uskollinen ja mahtava. Se pysyy rinnallasi kaikesta huolimatta. Mutta useimmiten se haluaa vain nukkua. Koko ajan. Sinun on kerrottava sille, milloin haluat sen pysyvän hereillä. Hyvä koira!

Yhdessä, mutta erikseen #

Sivuasi voi hallita vain yksi palvelutyöntekijä kerrallaan. Mutta siihen voi olla asennettuna kaksi palvelutyöntekijää kerrallaan. Kun teet muutoksen palvelutyöntekijän koodiin ja päivität sivun, et varsinaisesti muokkaa palvelutyöntekijääsi lainkaan. Palvelutyöntekijät ovat muuttumattomia. Sen sijaan teet kokonaan uuden. Tämä uusi palvelutyöntekijä (sanotaan sitä SW2:ksi) asennetaan, mutta se ei vielä aktivoidu. Sen on odotettava, että nykyinen palvelutyöntekijä (SW1) lopettaa toimintansa (kun käyttäjäsi poistuu sivustoltasi).

Messing with another service worker’s caches #

Asennuksen aikana SW2 voi saada asioita kuntoon – yleensä luoda ja täyttää välimuistit. Mutta varokaa: tällä uudella palvelutyöntekijällä on pääsy kaikkeen, mihin nykyisellä palvelutyöntekijällä on pääsy. Jos et ole varovainen, uusi odottava palvelutyöntekijä voi todella sotkea nykyisen palvelutyöntekijän asiat. Joitakin esimerkkejä, jotka voivat aiheuttaa ongelmia:

  • SW2 voi poistaa välimuistin, jota SW1 käyttää aktiivisesti.
  • SW2 voi muokata SW1:n käyttämän välimuistin sisältöä, mikä saa SW1:n vastaamaan varoilla, joita sivu ei odota.

Skip skipWaiting #

Palvelutyöntekijä voi myös käyttää riskialtista skipWaiting()-metodia ottaakseen sivun hallinnan haltuunsa heti asennuksen päätyttyä. Tämä on yleensä huono ajatus, ellet tarkoituksella yritä korvata bugista service workeria. Uusi palveluntyöläinen saattaa käyttää päivitettyjä resursseja, joita nykyinen sivu ei odota, mikä johtaa virheisiin ja vikoihin.

Aloita puhtaasti #

Tapa estää palveluntyöläisiäsi pöllimästä toisiaan on varmistaa, että ne käyttävät eri välimuisteja. Helpoin tapa toteuttaa tämä on versioida niiden käyttämät välimuistien nimet.

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

Kun otat käyttöön uuden palveluntyöläisen, bumppaat version niin, että se tekee tarvitsemansa edellisestä palveluntyöläisestä täysin erillisellä välimuistilla.

End clean #

Kun palveluntyöläisesi saavuttaa tilan activated, tiedät, että se on ottanut komennon haltuunsa ja että edellinen palveluntyöläinen on redundantti (ts, ei enää tarvita). Tässä vaiheessa on tärkeää siivota vanhan palvelutyöntekijän jäljet. Sen lisäksi, että se kunnioittaa käyttäjien välimuistitallennusrajoituksia, se voi myös estää tahattomat virheet.

caches.match()-metodi on usein käytetty oikotie kohteen hakemiseen mistä tahansa välimuistista, jossa on vastaavuus. Se kuitenkin käy läpi kätköt siinä järjestyksessä kuin ne on luotu. Oletetaan siis, että sinulla on kaksi versiota skriptitiedostosta app.js kahdessa eri välimuistissa – assets-1 ja assets-2. Sivusi odottaa uudempaa skriptiä, joka on tallennettu tiedostoon assets-2. Mutta jos et ole poistanut vanhaa välimuistia, caches.match('app.js') palauttaa vanhan version assets-1:sta ja todennäköisesti rikkoo sivustosi.

Ainut, mitä edellisen palveluntyöläisen jälkeen siivoamiseen tarvitaan, on poistaa kaikki välimuistit, joita uusi palveluntyöläinen ei tarvitse:

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

Palveluntyöläisesi estäminen tukkimasta toisiaan vaatii hieman työtä ja kurinalaisuutta, mutta se on vaivan arvoista.

Ajattele palveluntyöläisesi ja sivustosi yhdistelmää asennettavana sovelluksena. Jokaisen version pitäisi toimia. Jokaisen version pitäisi olla erillään toisistaan. Kuvittele, kuinka buginen peli olisi, jos kehittäjä julkaisisi vahingossa patchin, joka käyttäisi uutta pelilogiikkaa, mutta vanhentuneita assetteja. Raivostuisit foorumeilla niin nopeasti! Pidä sovelluksen versiot siisteinä & puhtaina.

Palvelutyöntekijöiden ajattelutapa #

Sitoutuminen oikeaan ajattelutapaan palvelutyöntekijöitä ajatellessasi auttaa sinua rakentamaan omasi luottavaisesti. Kun saat niistä otteen, voit luoda uskomattomia kokemuksia käyttäjillesi.

Jos haluat ymmärtää kaiken tämän pelaamalla peliä, olet onnekas! Mene pelaamaan Service Workies -peliä, jossa opit palvelutyöntekijän tavat tappaaksesi offline-pedot.

Viimeksi päivitetty: Jun 4, 2019 Paranna artikkelia

Vastaa

Sähköpostiosoitettasi ei julkaista.