Les travailleurs de service sont puissants et méritent absolument d’être appris. Ils vous permettent d’offrir un tout nouveau niveau d’expérience à vos utilisateurs. Votre site peut se charger instantanément. Il peut fonctionner hors ligne. Il peut être installé comme une application native et se sentir tout aussi poli-mais avec la portée et la liberté du web.

Mais les travailleurs de service sont différents de tout ce que la plupart d’entre nous, les développeurs web, sont habitués. Ils viennent avec une courbe d’apprentissage abrupte et une poignée d’accrocs auxquels vous devez faire attention.

Google Developers et moi avons récemment collaboré sur un projet-Service Workies-un jeu gratuit pour comprendre les travailleurs de service. En le construisant et en travaillant avec les tenants et aboutissants complexes des travailleurs de service, j’ai rencontré quelques accrocs. Ce qui m’a le plus aidé a été de trouver une poignée de métaphores descriptives. Dans ce post, nous allons explorer ces modèles mentaux et envelopper nos cerveaux autour des traits paradoxaux qui rendent les travailleurs de service à la fois délicats et impressionnants.

Le même, mais différent #

Lorsque vous coderez votre travailleur de service, beaucoup de choses vous sembleront familières. Vous pouvez utiliser vos nouvelles fonctionnalités préférées du langage JavaScript. Vous écoutez les événements du cycle de vie tout comme les événements de l’interface utilisateur. Vous gérez le flux de contrôle avec des promesses comme vous en avez l’habitude.

Mais d’autres comportements du travailleur de service vous font vous gratter la tête en toute confusion. Surtout lorsque vous rafraîchissez la page et ne voyez pas vos modifications de code appliquées.

Une nouvelle couche #

Normalement, lorsque vous construisez un site, vous n’avez que deux couches à penser : le client et le serveur. Le travailleur de service est une toute nouvelle couche qui se trouve au milieu.

Pensez à votre travailleur de service comme une sorte d’extension de navigateur – une que votre site peut installer dans le navigateur de votre utilisateur. Une fois installé, le travailleur de service étend le navigateur de votre site avec une couche intermédiaire puissante. Cette couche de travailleur de service peut intercepter et traiter toutes les demandes que votre site fait.

La couche de travailleur de service a son propre cycle de vie indépendant de l’onglet du navigateur. Un simple rafraîchissement de page ne suffit pas à mettre à jour un travailleur de service – tout comme vous ne vous attendez pas à ce qu’un rafraîchissement de page mette à jour le code déployé sur un serveur. Chaque couche a ses propres règles uniques de mise à jour.

Dans le jeu Service Workies, nous couvrons les nombreux détails du cycle de vie du travailleur de service et nous vous donnons une tonne de pratique pour travailler avec lui.

Pensez à votre travailleur de service comme une nouvelle couche intermédiaire avec son propre cycle de vie et ses méthodes de mise à jour.

Puissant, mais limité #

Avoir un travailleur de service sur votre site vous donne des avantages incroyables. Votre site peut :

  • fonctionner parfaitement même lorsque l’utilisateur est hors ligne
  • obtenir des améliorations massives des performances grâce à la mise en cache
  • utiliser les notifications push
  • être installé en tant que PWA

Avec tout ce que les travailleurs de service peuvent faire, ils sont limités par la conception. Ils ne peuvent rien faire de synchrone ou dans le même thread que votre site. Cela signifie donc qu’ils n’ont pas accès à :

  • localStorage
  • the DOM
  • the window

La bonne nouvelle, c’est qu’il existe une poignée de façons dont votre page peut communiquer avec son travailleur de service, y compris des postMessagecanaux de messages directs, un à un, et des canaux de diffusion un à plusieurs.

Pensez à votre travailleur de service comme quelque chose qui vit à l’extérieur de votre page. Vous pouvez lui parler, mais il ne peut pas accéder directement à votre page.

Longue durée de vie, mais courte durée de vie #

Un travailleur de service actif continue à vivre même après qu’un utilisateur quitte votre site ou ferme l’onglet. Le navigateur conserve ce travailleur de service afin qu’il soit prêt la prochaine fois que l’utilisateur reviendra sur votre site. Avant que la toute première demande ne soit faite, le travailleur de service a la possibilité de l’intercepter et de prendre le contrôle de la page. C’est ce qui permet à un site de fonctionner hors ligne – le travailleur de service peut servir une version en cache de la page elle-même, même si l’utilisateur n’a pas de connexion à Internet.

Dans Service Workies, nous visualisons ce concept avec Kolohe (un travailleur de service amical) interceptant et traitant les demandes.

Stopped #

Malgré que les travailleurs de service semblent être immortels, ils peuvent être arrêtés à presque tout moment. Le navigateur ne veut pas gaspiller des ressources sur un travailleur de service qui ne fait rien actuellement. Être arrêté n’est pas la même chose que d’être résilié – le travailleur de service reste installé et activé. Il est simplement mis en veille. La prochaine fois qu’il est nécessaire (par exemple, pour traiter une requête), le navigateur le réveille.

waitUntil #

En raison de la possibilité constante d’être mis en sommeil, votre travailleur de service a besoin d’un moyen de faire savoir au navigateur quand il fait quelque chose d’important et n’a pas envie de faire une sieste. C’est là que event.waitUntil() entre en jeu. Cette méthode prolonge le cycle de vie dans lequel il est utilisé, l’empêchant à la fois d’être arrêté et de passer à la phase suivante de son cycle de vie jusqu’à ce que nous soyons prêts. Cela nous donne le temps d’installer des caches, de récupérer des ressources sur le réseau, etc.

Cet exemple indique au navigateur que notre travailleur de service n’a pas fini de s’installer tant que le cache assets n’a pas été créé et peuplé de l’image d’une épée:

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

Attention à l’état global #

Lorsque ce démarrage/arrêt se produit, la portée globale du travailleur de service est réinitialisée. Faites donc attention à ne pas utiliser d’état global dans votre travailleur de service ou vous serez triste la prochaine fois qu’il se réveillera et aura un état différent de celui auquel il s’attendait.

Considérez cet exemple qui utilise un état global :

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

À chaque requête, ce travailleur de service enregistrera un nombre – disons 0.13981866382421893. La variable hasHandledARequest passe également à true. Maintenant, le travailleur de service reste inactif pendant un peu, donc le navigateur l’arrête. La prochaine fois qu’il y a une demande, le travailleur de service est à nouveau nécessaire, donc le navigateur le réveille. Son script est à nouveau évalué. Maintenant hasHandledARequest est réinitialisé à false, et favoriteNumber est quelque chose de complètement différent-0.5907281835659033.

Vous ne pouvez pas compter sur un état stocké dans un service worker. De plus, la création d’instances de choses comme les canaux de messages peut causer des bogues : vous obtiendrez une toute nouvelle instance chaque fois que le travailleur de service s’arrête/démarre.

Avertissement : Cet accroc est particulièrement important à garder à l’esprit lorsque vous travaillez sur votre code de travailleur de service, car lorsque Chrome DevTools est ouvert, le comportement de démarrage/arrêt est désactivé. Il se peut que vous ne voyiez même pas les bogues causés par la dépendance à l’état global jusqu’à ce qu’ils aient été expédiés à vos utilisateurs.

Dans le chapitre 3 de Service Workies, nous visualisons notre travailleur de service arrêté comme perdant toute couleur pendant qu’il attend d’être réveillé.

Pensez à votre travailleur de service comme un chien fouetté. Il est rapide, loyal et génial. Il restera à vos côtés quoi qu’il arrive. Mais surtout, il veut juste dormir. Tout le temps. Vous devez lui faire savoir quand vous voulez qu’il reste éveillé. Bon chien!

Ensemble, mais séparé #

Votre page ne peut être contrôlée que par un seul travailleur de service à la fois. Mais elle peut avoir deux travailleurs de service installés en même temps. Lorsque vous apportez une modification au code de votre travailleur de service et rafraîchissez la page, vous ne modifiez pas du tout votre travailleur de service. Les Service Workers sont immuables. Au lieu de cela, vous en créez un tout nouveau. Ce nouveau travailleur de service (appelons-le SW2) s’installera mais ne sera pas encore activé. Il doit attendre que le travailleur de service actuel (SW1) se termine (lorsque votre utilisateur quitte votre site).

Modifier les caches d’un autre travailleur de service #

Pendant l’installation, SW2 peut obtenir des choses à configurer – habituellement créer et remplir les caches. Mais attention : ce nouveau travailleur de service a accès à tout ce à quoi le travailleur de service actuel a accès. Si vous ne faites pas attention, votre nouveau travailleur de service en attente peut vraiment mettre la pagaille dans votre travailleur de service actuel. Quelques exemples qui pourraient vous causer des ennuis :

  • SW2 pourrait supprimer un cache que SW1 utilise activement.
  • SW2 pourrait modifier le contenu d’un cache que SW1 utilise, faisant en sorte que SW1 réponde avec des actifs que la page n’attend pas.

Skip skipWaiting #

Un travailleur de service peut également utiliser la méthode risquée skipWaiting() pour prendre le contrôle de la page dès qu’il a terminé son installation. C’est généralement une mauvaise idée, sauf si vous essayez intentionnellement de remplacer un travailleur de service bogué. Le nouveau travailleur de service pourrait utiliser des ressources mises à jour que la page actuelle n’attend pas, ce qui entraîne des erreurs et des bogues.

Démarrer proprement #

La façon d’empêcher vos travailleurs de service de se clobber les uns les autres est de s’assurer qu’ils utilisent des caches différents. La façon la plus simple d’accomplir cela est de versionner les noms de cache qu’ils utilisent.

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

Lorsque vous déployez un nouveau travailleur de service, vous ferez sauter le version afin qu’il fasse ce dont il a besoin avec un cache entièrement séparé du travailleur de service précédent.

End clean #

Une fois que votre travailleur de service atteint l’état activated, vous savez qu’il a pris le relais, et que le travailleur de service précédent est redondant (c’est-à-dire, n’est plus nécessaire). À ce stade, il est important de faire le ménage après l’ancien travailleur de service. Non seulement cela respecte les limites de stockage du cache de vos utilisateurs, mais cela peut aussi éviter des bugs involontaires.

La méthode caches.match() est un raccourci souvent utilisé pour récupérer un élément dans n’importe quel cache où il y a une correspondance. Mais elle itère à travers les caches dans l’ordre où ils ont été créés. Disons que vous avez deux versions d’un fichier script app.js dans deux caches différents –assets-1 et assets-2. Votre page attend le script le plus récent qui est stocké dans assets-2. Mais si vous n’avez pas supprimé l’ancien cache, caches.match('app.js') va retourner l’ancien de assets-1 et très probablement casser votre site.

Tout ce qu’il faut pour faire le ménage après les précédents travailleurs de service est de supprimer tout cache dont le nouveau travailleur de service n’a pas besoin:

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

Prévenir vos travailleurs de service de se clobber les uns les autres demande un peu de travail et de discipline mais en vaut la peine.

Pensez à la combinaison de votre travailleur de service et de votre site comme une application installable. Chaque version devrait fonctionner. Chaque version devrait être séparée des autres. Imaginez à quel point un jeu serait bogué si le développeur publiait accidentellement un patch qui utilise une nouvelle logique de jeu mais des actifs obsolètes. Vous vous déchaîneriez si vite sur les forums ! Gardez vos versions d’applications bien & propres.

Etat d’esprit du travailleur de service #

S’installer dans le bon état d’esprit tout en pensant aux travailleurs de service vous aidera à construire le vôtre avec confiance. Une fois que vous les aurez compris, vous serez en mesure de créer des expériences incroyables pour vos utilisateurs.

Si vous voulez comprendre tout cela en jouant à un jeu, alors vous avez de la chance ! Allez jouer à Service Workies où vous apprendrez les manières du travailleur de service afin de tuer les bêtes hors ligne.

Dernière mise à jour : 4 juin 2019 Améliorer l’article

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.