Vil du prøve at finde ud af, hvad en service worker er? Du er ikke alene!
En Service Worker er et script, der udføres i baggrunden, i en separat tråd fra browserens brugergrænseflade. Service worker-cache gør det muligt for et websted at fungere offline. De er det tekniske kraftcenter, der gør et websted til en progressiv webapp. De muliggør dyb platformintegration, som f.eks. rig caching, push-meddelelser og baggrundssynkronisering.
Service workers er designet til at være en udvidelig platform, yderligere funktioner er under planlægning.
De kan ikke få adgang til DOM, men kan opsnappe alle netværksanmodninger. Dette giver udviklere mulighed for at kontrollere, hvordan anmodninger håndteres, hvilket giver en rig mulighed for at få websteder til at fungere offline.
Service workers er blevet kaldt en game changer for internettet. Jeg tror ikke, at det er en simpel overdrivelse, for de muliggør mange meget nødvendige funktioner og gør den kernearkitektur, jeg har brugt i årevis, indfødt.
Service Workers lyder fantastisk!
Dette er den vigtigste teknologi eller moderne web-API bag Progressive Web Applications. Uden en service worker er et websted bare et websted, tilføj en service worker, og du har nu en applikation.
Der er nogle vigtige funktioner ved service workers, som du skal forstå:
- En service worker er en JavaScript-fil
- De udføres på en separat tråd fra brugergrænsefladen
- De kan ikke få direkte adgang til DOM
- Der er en livscyklus eller en række begivenheder, som en service worker gennemløber for at blive aktiv, forklares senere
- De er kun levende, mens de bruges, så ingen belastning af batteriet
- De er isoleret til den oprindelse eller det domæne, de er registreret med
- Service Workers kræver HTTPS
- Kan sende meddelelser til og fra brugergrænsefladen
- Kræver ikke en åben webside for at fungere
- Understøttes af alle større browsere, herunder iOS Safari
- Ligner Web Workers, men er bedre på mange måder
- Hvordan fungerer Service Workers?
- Service Worker Extensibility
- Service Worker Life Cycle
- Hvor længe skal Service Workers vare?
- Hvordan kontrollerer jeg, om en Service Worker er registreret?
- Hvordan afregistrerer jeg en Service Worker
- Service Worker Caching
- Hvordan opdaterer jeg min Service Worker Cache
- Hvilke browsere understøtter Service Workers?
- Hvad er forskellen mellem en Service Worker og en Web Worker
- Hvad en Service Worker ikke kan gøre
Hvordan fungerer Service Worker?
En Service Worker sidder mellem browseren og netværket og fungerer som en proxyserver, der håndterer en række ikke-UI-centrerede opgaver. De er begivenhedsdrevne og lever uden for browserprocessen, hvilket gør det muligt for dem at arbejde uden en aktiv browsersession. Tjenestearbejderen er et script, der udføres i en tråd, adskilt fra brugergrænsefladen. Dette gør det muligt for servicearbejderen at udføre ikke-UI-opgaver, hvilket får et websted til at yde bedre.
Servicearbejderne afsluttes, når de ikke er i brug, og genoprettes, når det er nødvendigt, hvilket forhindrer dem i at belaste CPU’en og dræne batterierne. De fungerer som en programmerbar netværksproxy eller mellemmand mellem browseren og netværket, hvilket giver udviklerne mulighed for at designe, hvordan netværksanmodninger håndteres.
Den første styrke, som en service worker giver et websted, er muligheden for at aktivere offlinefunktioner med granulær kontrol. Dette gøres med en rig cache-API og ved at opsnappe alle netværksanmodninger, før de forlader stedet.
Caching muliggør ikke kun offlineoplevelser, men websteder kan også indlæses øjeblikkeligt, når de hentes fra cache. Service worker-caching gør netværket til en progressiv forbedring eller er ikke nødvendigt for at gøre webstedet brugbart.
Service Worker Extensibility
En undervurderet service worker-funktion er dens udvidelsesmuligheder Service workers er designet til at være den rygrad, der understøtter yderligere funktionalitet. De to første funktioner, der leveres i browsere, er native push-meddelelser og baggrundssynkronisering. Flere nye API’er diskuteres i øjeblikket og bør begynde at dukke op i browsere i den nærmeste fremtid.
Service workers lever i deres egen tråd og har ikke adgang til DOM. De har også deres eget globale omfang, som der henvises til ved hjælp af objektet “self”.
De kræver også, at et websted serveres ved hjælp af HTTPS. Dette krav skyldes de kraftfulde funktioner, som service workers tilbyder. HTTPS forhindrer mange almindelige angreb. I dag bør alle websteder serveres ved hjælp af HTTPS, da barriererne for implementering er blevet løftet og den minimale sikkerhed, de tilbyder.
De er også asynkrone. Det betyder, at alle API’er understøtter promises. Det betyder også, at visse API’er og funktioner ikke er tilgængelige i service workers. Den mest bemærkelsesværdige er localStorage. I stedet skal data lagres ved hjælp af IndexedDB.
Service Worker Life Cycle
Hvor man dykker ned i disse fantastiske service worker-funktioner, skal udviklere forstå livscyklusen.
En service worker skal registreres af et websted. Da nogle browsere stadig ikke understøtter service workers, bør du udføre et funktionstjek, før du registrerer en service worker. Dette gøres ved at kontrollere for tilstedeværelsen af “serviceWorker” i navigator.
if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js') .then(function(registration) { // Registration was successful }) .catch(function(err) { // registration failed :( }); }
For at registrere servicearbejderen skal du kalde navigator.serviceWorker.register. Overgiv stien til servicemedarbejderen. Register-funktionen returnerer et løfte.
Hvis det lykkes, returnerer løftet en reference til registreringsobjektet for servicearbejderen. Herfra kan du udføre specifikke UI-opgaver efter behov.
Standard Service Worker-hændelser
- install
- activate
- fetch
- push (understøttes ikke af Safari)
- sync (understøttes ikke af de fleste browsere endnu)
Når en service worker er registreret, vises “install”-hændelsen. I denne begivenhed er den mest almindelige opgave at udføre kaldes pre-caching.
Pre-caching er hvor en foruddefineret liste over aktivfiler, der er nødvendige for at danne en side eller et websted, og tilføje dem til cache, før de anmodes. Dette udnytter servicearbejderen cache til at persistere disse svar.
self.addEventListener("install", event => { event.waitUntil( caches.open(preCacheName) .then(function (cache) { return cache.addAll(precache_urls); }) ); });
Installationshændelsen udløses kun én gang i en servicearbejders levetid. Hændelsen udløses ikke igen, før servicearbejderen opdateres.
Den næste begivenhed, der udløses som en del af registreringens livscyklus, er “activate”. Når en servicemedarbejder installeres, bliver den ikke straks aktiv. Den naturlige rækkefølge er, at en ny servicemedarbejder venter, indtil alle servicemedarbejder-“klienter” er lukket.
Grunden til, at servicemedarbejdere er designet til ikke at tage over med det samme, er for at forhindre, at de ødelægger brugeroplevelsen.
Funktionen skipWaiting tvinger en ventende servicemedarbejder til at blive aktiv. Dette bør kun anvendes, når du er sikker på, at den nye servicemedarbejder ikke vil ødelægge eksisterende klienter.
self.skipWaiting();
Når servicemedarbejderen bliver aktiv, udløses begivenheden ‘activate’.
self.addEventListener("activate", event => { //on activate event.waitUntil(clients.claim()); });
Denne begivenhed bruges almindeligvis til at udføre oprydnings- eller migreringsopgaver. F.eks. fjernelse af gamle caches, der kan være i konflikt med de nye servicemedarbejdercaches.
Hvor længe skal servicemedarbejdere vare?
Der er ingen fast regel for, hvor længe en browser holder en servicemedarbejder kørende. Internt bruger browserens motor et sæt heuristikker til at afgøre, hvornår service worker-processen skal afsluttes.
Helt generelt, hvis en webside er inaktiv, vil processen spinne ned efter et minut eller to, måske allerede efter 30 sekunder.
Den præcise tid vil i virkeligheden afhænge af hardware, brugsmønstre osv.
Den gode nyhed er, at det kun tager en håndfuld millisekunder at tænde en service worker. Det er så hurtigt, at du ikke rigtig vil bemærke nogen latenstid. Du behøver heller ikke at programmere noget særligt for at håndtere et scenarie uden service worker, dit websted vil bare fungere. Magien ved progressiv forbedring.
Hvordan kan jeg kontrollere, om en service worker er registreret?
Der er flere måder at kontrollere, om en service worker er registreret på. Den nemmeste er at kalde serviceworkers.getRegistrations-metoden.
navigator.serviceWorker.getRegistrations().then(registrations => { console.log(registrations); });
Dette er kode, du kan tilføje til scriptet på dine sider for at logge registreringen til teknisk support eller debugging af udviklere.
Metoden ‘getRegistrations’ returnerer et array af alle servicemedarbejdere, der er registreret under det aktuelle område eller websted.
Hvis du blot logger registreringen til konsollen, er det bedre at se fanen Dev Tools ‘Application’. Den har et underpanel, der viser et visuelt billede af den oprindeligt registrerede servicemedarbejder. Du kan også udløse baggrundssynkroniseringsbegivenheder og teste push-meddelelser.
Du kan også slette servicemedarbejderen, fremtvinge en opdatering og anden generel administration, der hjælper med udviklingen.
Den virkelige værdi getRegistrations tilbyder, er til en slags bagdørssupportfunktion. Vi ved alle, hvordan det er at forsøge at hjælpe nogen eksternt, og du kan ikke få adgang til DevTools for virkelig at foretage fejlfinding på problemet. Nogle gange vil man ønske en slags visuel supportside eller modal for at give oplysninger om programtilstanden.
Den gennemsnitlige forbruger vil ikke vide, hvordan man får adgang til DevTools-konsolpanelet. I stedet kan du oprette en brugergrænseflade i applikationen for at give genlyd af service worker-registreringsobjektets egenskaber.
Hvordan afregistrerer jeg en service worker
Håbenligt vil du ikke støde på et scenarie, hvor din service worker-kode har skabt en brugeroplevelsesfejl. Hvis du gør det, er der nogle få ting, du kan gøre for at fjerne eller afregistrere en service worker.
De fleste scenarier, hvor du har brug for at fjerne en service worker, vil være, når du udvikler programmet. I dette tilfælde kan du bruge DevTools til at fjerne eller slette servicemedarbejderen.
Hvis du har brug for at fjerne eller slette en implementeret service worker, bliver det lidt mere tricky. Der er programmatiske metoder til at få dig ud af kniben.
Læs mere om fjernelsesteknikker.
Service Worker Caching
Specifikationen for service workers omfatter native caching-funktioner. Dette erstatter den traditionelle appCache, der har forårsaget mange forvaltningsproblemer, siden den blev oprettet. Service worker-caching er meget mere håndterbar.
Cache-API’et giver et persistenslager, der gemmer netværkssvar, som kan forespørges af den matchende anmodning.
Nøglen til at bruge service worker-caching er service worker-hændelsen “fetch”. Denne begivenhed udløses for hver netværksanmodning, så du kan opsnappe anmodningen og kontrollere, om svaret er blevet cachet, før det sendes til netværket.
Gennem at få adgang til aktiver i den lokale cache kan du undlade dyre netværksanmodninger. Det betyder, at webstedet kan fungere, når der ikke er noget netværk, offline eller dårlig netværksforbindelse, lave barer eller falsk mobilforbindelse (kendt som LiFi).
self.addEventListener("fetch", event => { event.respondWith( fetchFromCache(event) .catch(() => fetch(request) .then(response => addToCache(cacheKey, request, response)) .catch(() => offlineResponse(resourceType, opts)) ) ); });
I eksemplet ovenfor kontrollerer koden, om et svar tidligere er blevet cachelagret. Hvis det er tilfældet, returneres det cachede svar. Hvis ikke, sendes anmodningen videre til netværket.
Når anmodningen vender tilbage, cachelagres svaret og returneres til brugergrænsefladen.
Hvis netværket svigter, falder logikken tilbage til et offline-svar.
Der er mange bevægelige dele, der anvendes i eksempelkoden. Jeg vil give flere detaljer i en opfølgende artikler.
Hvordan opdaterer jeg min Service Worker Cache
En almindelig misforståelse er, at når du cacher en netværksanmodning, er den gemt for evigt. Dette er ikke tilfældet. Du har fuld kontrol over, hvornår og hvordan cachen bliver ugyldiggjort og opdateret.
Dette er et meget komplekst og involveret emne. Jeg tror, at jeg personligt kan detaljeret omkring 3 dusin caching strategier, alle involverer en måde at styre cache invalidering eller opdatering af cachen.
Jeg tror, at nøglen til invalidering er at bestemme enten en tid til at invalidere (time to live) værdi, et manifest eller en baggrundsopdateringsproces. I sidstnævnte kan du lave en HEAD-forespørgsel for at se, om der er foretaget en opdatering på serveren ved at sammenligne den senest opdaterede headerværdi med det tidspunkt, hvor svaret blev cachet.
Der er ikke et enkelt svar for alle programmer. Du skal planlægge din strategi og være forberedt på at justere, efterhånden som du ser, hvordan din applikation bruges.
Hvilke browsere understøtter service workers?
Alle moderne browsere understøtter service workers, i det mindste caching. Chrome, FireFox og Edge understøtter native push-notifikationer, og Chrome og Edge har understøttelse af baggrundssynkronisering.
Det betyder, at de centrale PWA-funktioner er tilgængelige på alle enheder og i alle browsere. Push og baggrundssynkronisering er forbedringer.
Vi har bygget flere Progressive Web Apps, der krævede sofistikerede offline caching-strategier for at lade programmerne fungere offline, selv på iOS. Disse applikationer kræver, at alle anmodninger, selv POST-, PUT- og DELETE-handlinger, lagres i cache i en kø. Vi fik disse applikationer til at synkronisere selv på iOS, når forbindelserne vidste at være tilgængelige.
Hvad er forskellen mellem en service worker og en webworker
Service workers og web workers er lignende værktøjer. Begge udfører processer i en separat tråd fra brugergrænsefladen. Den virkelige forskel ligger i den faktiske brugskontekst.
Ingen af dem har adgang til DOM- eller vinduesobjektet. De er bedre til mellemniveauet eller lange, procesintensive opgaver.
Web workers kører kun, når en webside er åben, og en opgave udløses fra et script på siden.
En service worker kan også udføres, når en side er åben, men kan også udløses af en platformshændelse som f.eks. en push-meddelelse. En webside behøver ikke at være åben, for at en service worker kan udføres.
Service workers fungerer også som en proxy mellem netværket og brugergrænsefladen. Hvis der bruges en side (det mest almindelige scenarie), passerer alle HTTPS-netværksanmodninger gennem servicearbejderen, som du lærte i afsnittet om caching.
Kommunikationen mellem brugergrænsefladen og begge arbejdere foregår ved hjælp af postMessage-metoden og message-hændelsen. Hvis du har lavet programmering med flere tråde, er denne model meget velkendt.
Hvad en servicearbejder ikke kan gøre
Servicearbejdere kan ikke få adgang til vinduesobjektet
Vinduesobjektet udføres i brugergrænsefladetråden, adskilt fra servicearbejdertråden. Det betyder, at en servicemedarbejder ikke kan manipulere DOM-elementer direkte. Tjenestearbejderen og vinduet kan kommunikere via postMessage-metoden. Dette gør det muligt at sende meddelelser frem og tilbage. Du skal have logik på hver side for at behandle beskederne og udløse forskellige arbejdsgange.
Service Workers kræver HTTPS
Da Service Workers har så mange muligheder, er de kun aktiveret, hvis siden serveres med HTTPS. Dette sikrer et sikkerhedsniveau, der gør det muligt for servicearbejderen at gøre de ting, den er designet til.
Over HTTP ville servicearbejderen være modtagelig for man in the middle-angreb. Udviklere kan arbejde på localhost, hvilket forhindrer os i at installere et lokalt TLS-certifikat.
Med andre ord er svaret på spørgsmålet om, hvorvidt en service worker fungerer på HTTP, nej. Webstedet vil stadig rendere, men servicearbejderen registreres ikke og udføres ikke.
Er kun asynkrone
Servicearbejdere er asynkrone, hvilket betyder, at de bruger og er afhængige af Promises og API’er, der bruger Promises. Det betyder, at synkrone API’er som XHR og localStorage ikke er tilgængelige for en service worker. Frygt ikke, du kan bruge Fetch API’et (som erstattede XHR) og IndexedDB. De fleste API’er, der ikke interagerer direkte med vinduesobjektet, er tilgængelige i en service worker.