Mise à jour de votre PWA en production

Avez-vous entendu la blague selon laquelle si vous avez installé ServiceWorker, il est temps de changer de domaine? Maintenant, je vais vous dire quelle est sa signification et que faire si vous décidez toujours que vous avez besoin d'une PWA.





Dans les instructions pour le type de tel ou tel ServiceWorker et de son utilisation, presque aucune attention n'est accordée. Et je suis sûr que des articles comme celui-ci sont la première chose que vous lisez avant d'utiliser. Mais au moment où, après de tels articles, votre PWA fraîchement préparée est enfin apparu en production et que les utilisateurs ont eu la possibilité d'ajouter une autre icône à leur bureau, sachez que vous avez dépassé le point de non-retour.





Avec votre permission, je ne m'attarderai pas sur la description de Service Worker (ci-après SW) et sur son fonctionnement. Habré a déjà un bon article à ce sujet . Peu importe le logiciel que vous avez en particulier. Peut-être que vous utilisez create-react-app , ce qui signifie que la bibliothèque Workbox est responsable du logiciel . Peut-être avez-vous implémenté SW vous-même, avec une stratégie de mise en cache délicate. La pile n'est pas vraiment importante. La même documentation de l'ARC indique que tout ce dont vous avez besoin est de changer une ligne et d'obtenir tous les plaisirs d'un comportement semblable à une application. Vous avez écrit .register()



et attendez le résultat. Et vous l'aurez.





La prochaine fois qu'un client mécontent vous demandera de changer la couleur de ce bouton orange ou enfin de résoudre ce bug de focalisation volante, vous vous retrouverez dans une situation incroyable. Il y a un correctif dans le référentiel, le conteneur est assemblé et nginx distribue la dernière version à coup sûr, mais le client n'est toujours pas satisfait pour une raison quelconque. Oh oui, nous sommes maintenant PWA.





- Veuillez actualiser la page. Comment cela n'aide-t-il pas? Et si CTRL + R?





Alors, que faire lorsque l'actualisation frénétique de la page n'aide pas et que le client voit toujours le bouton orange moqueur?





Il est important de se rappeler que SW essaie de se comporter comme une application de bureau.





Rappelons-nous comment l'application de bureau se met à jour. Il télécharge le nouveau programme d'installation, supprime l'ancienne version et la réinstalle. Ce n'est qu'alors que l'utilisateur reçoit une nouvelle version de l'application.





SW.





SW : installing, waiting active. Active - , SW. installing waiting SW active. installing SW , . waiting , SW ( ). .





SW, , - . SW , . . , . , .





, , "". , SW : , , , . , SW . , .





SW installing, waiting active. - . , .





, , .





№1: SW

( ) - SW. SW skipWaiting()



, . SW . "" .

: , . , skipWaiting()



, , .





№2: SW

, . navigator.serviceWorker



controllerchange



, SW . installing.

skipWaiting()



, . :





navigator.serviceWorker.addEventListener('controllerchange',  ()  => window.location.reload());
      
      



SW , .

, , . , , . .





№3:

, , SW , - - .





controllerchange



, , , .

, SW, ServiceWorkerRegistration



. .register()



, . API . , update()



, SW . , .





(active) SW navigator.serviceWorker.controller



active . (waiting) (installing) SW.





SW postMessage()



, iframe , API. SW . SW.





addEventListener('message', ev => {  
  if (ev.data === 'skipWaiting') return skipWaiting();
});
      
      



Workbox CRA, .





Ensuite, nous devons suivre l'apparence du SW en attente. À mon avis, il vaut mieux ne pas réagir à chaque fois à SW avec le statut d'installation, comme cela est écrit dans certains guides, mais attendre que l'objet d'enregistrement SW revienne vrai sur le terrain waiting



. Cela ralentira la mise à jour, mais ne déclenchera pas votre modal lorsque le logiciel est installé pour la première fois.





Après avoir attendu le SW en attente, nous appelons une fenêtre modale dans laquelle l'utilisateur peut confirmer la mise à jour. Sur confirmation, nous appelons skipWaiting()



et rechargeons de force la page comme décrit ci-dessus. En cas d'échec, la mise à jour sera retardée. Le code dans mon cas ressemblera à ceci:





//   
const askUserToUpdate = reg => {
  return Modal.confirm({
    onOk: async () => {
      //    
      navigator.serviceWorker.addEventListener('controllerchange', () => {
        window.location.reload();
      });

      //   
      if (reg && reg.waiting) {
        reg.waiting.postMessage({ type: 'SKIP_WAITING' });
      }
    },

    onCancel: () => {
      Modal.destroyAll();
    },
    icon: null,
    title: ' ! 
      
      










All Articles