Actualización de su PWA en producción

¿Ha escuchado el chiste de que si instaló ServiceWorker, es hora de cambiar el dominio? Ahora te diré cuál es su significado y qué hacer si, no obstante, decides que necesitas una PWA.





En las instrucciones para el tipo de este o este ServiceWorker y trabajar con él, casi no se presta atención. Y estoy seguro de que artículos como este son lo primero que lee antes de usar. Pero en el momento en que, después de tales artículos, su PWA recién horneada finalmente apareció en producción y los usuarios tuvieron la oportunidad de agregar otro ícono a su escritorio, sepa que ha pasado el punto sin retorno.





Con su permiso, no me detendré en la descripción de Service Worker (en adelante, SW) y cómo funciona. Habré ya tiene un buen artículo sobre esto . Ni siquiera importa qué software tengas específicamente. Tal vez esté usando create-react-app , lo que significa que la biblioteca Workbox es responsable del SW . Quizás implementó SW usted mismo, con alguna estrategia de almacenamiento en caché complicada. La pila no es realmente importante. La misma documentación de CRA dice que todo lo que necesita es cambiar una línea y obtener todos los placeres del comportamiento similar a una aplicación. Escribiste .register()



y esperas el resultado. Y lo conseguirás.





La próxima vez que un cliente descontento le pida que cambie el color de este botón naranja, o que finalmente resuelva ese error de enfoque volador, se encontrará en una situación increíble. Hay una revisión en el repositorio, el contenedor se ha ensamblado y nginx está distribuyendo exactamente la última versión, pero por alguna razón el cliente aún no está satisfecho. Oh, sí, ahora somos PWA.





- Actualice la página. ¿Cómo no ayuda? ¿Y si CTRL + R?





Entonces, ¿qué haces cuando la actualización frenética de la página no ayuda y el cliente todavía ve el botón naranja burlón?





Es importante recordar que SW intenta comportarse como una aplicación de escritorio.





Recordemos cómo se actualiza la aplicación de escritorio. Descarga el instalador nuevo, elimina la versión anterior y la reinstala. Solo entonces el usuario recibe una nueva versión de la aplicación.





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, .





A continuación, necesitamos rastrear la aparición del SW que espera. En mi opinión, es mejor no reaccionar cada vez que SW con el estado de instalación, como está escrito en algunas guías, sino esperar hasta que el objeto de registro SW devuelva verdadero en el campo waiting



. Esto ralentiza la actualización, pero no activa su modal cuando el SW se instala por primera vez.





Después de haber esperado el SW en espera, llamamos a una ventana modal en la que el usuario puede confirmar la actualización. Tras la confirmación, llamamos skipWaiting()



y recargamos la página a la fuerza como se describe anteriormente. Si ocurre una falla, la actualización se pospondrá. El código en mi caso se verá así:





//   
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