workers workbox una tutorial pwa instalar hacer framework examples español como apps app javascript service-worker sw-precache

javascript - workbox - Cómo: ServiceWorker comprueba si está listo para actualizar



service worker framework (2)

Lo que estoy tratando de lograr:

  • renderizar página con cargador / spinner

  • Si service-worker.js está registrado y activo, entonces service-worker.js actualizaciones

    • Si no hay actualizaciones, entonces retire el cargador
    • Si se ha updatefound y se ha instalado una nueva versión, vuelva a cargar la página.
  • más registrate service-worker.js
    • cuando updatefound , lo que significa que se instaló uno nuevo, elimine el cargador

Estoy usando el módulo sw-precache para generar service-worker.js y siguiendo el código de registro:

window.addEventListener(''load'', function() { // show loader addLoader(); navigator.serviceWorker.register(''service-worker.js'') .then(function(swRegistration) { // react to changes in `service-worker.js` swRegistration.onupdatefound = function() { var installingWorker = swRegistration.installing; installingWorker.onstatechange = function() { if(installingWorker.state === ''installed'' && navigator.serviceWorker.controller){ // updated content installed window.location.reload(); } else if (installingWorker.state === ''installed''){ // new sw registered and content cached removeLoader(); } }; } if(swRegistration.active){ // here I know that `service-worker.js` was already installed // but not sure it there are changes // If there are no changes it is the last thing I can check // AFAIK no events are fired afterwards } }) .catch(function(e) { console.error(''Error during service worker registration:'', e); }); });

Después de leer la spec , está claro que no hay controladores para algo como updatenotfound . Parece que serviceWorker.register verifica si service-worker.js cambió internamente al ejecutar el get-newest-worker-algorithm service-worker.js get-newest-worker-algorithm , pero no puedo ver métodos similares expuestos a través de la API pública.

Creo que mis opciones son:

  • espere unos segundos después de que el registro del trabajador de servicio se active para ver si se activa onupdatefound
  • dispare eventos personalizados desde el código service-worker.js si el caché no se actualizó

¿Cualquier otra sugerencia?

Editar:

Se me ocurrió un código que resuelve este problema mediante el uso de postMessage() entre el registro de SW y el cliente de SW (como se sugiere en @pate)

Tras la demostración, se intentan realizar comprobaciones a través del postMessage entre el cliente de SW y el registro de SW, pero falla porque el código de SW ya está almacenado en la caché

Editar:

Así que ahora parece que no puedo implementar lo que quiero porque:

  1. cuando el trabajador de servicio está activo, no puede buscar actualizaciones mediante la evaluación de algún código en el software. Este es el mismo software almacenado en caché, sin cambios.
  2. debe esperar a que se encuentre en la onupdatefound , no hay nada más que notifique los cambios en el SW
  3. activation de los SW más antiguos viene antes que onupdatefound
  4. Si no hay cambio, nada se dispara después de la activation
  5. La update() registro de SW update() es inmadura, sigue cambiando, Starting with Chrome 46, update() returns a promise that resolves with ''undefined'' if the operation completed successfully or there was no update
  6. la configuración del tiempo de espera para posponer la representación de la vista no es óptima ya que no hay una respuesta clara a cuánto tiempo se debe configurar, también depende del tamaño del SW

La única forma que aparece en mi mente es iniciar el cargador normalmente y luego eliminarlo en el trabajador de servicio, en la función de instalación. Voy a intentarlo en tu service-worker.js:

self.addEventListener(''install'', function(e) { console.log(''[ServiceWorker] Install''); e.waitUntil( caches.open(cacheName).then(function(cache) { console.log(''[ServiceWorker] Caching app shell''); return cache.addAll(filesToCache); }).then(function() { ***removeLoader();*** return self.skipWaiting(); }) ); });


La otra respuesta, proporcionada por Fabio, no funciona. El script de Service Worker no tiene acceso al DOM. No es posible eliminar nada del DOM o, por ejemplo, manipular los datos que manejan elementos del DOM desde dentro del Trabajador de servicios . Ese script se ejecuta por separado sin estado compartido.

Sin embargo, lo que puede hacer es enviar mensajes entre el JS real de la página y el trabajador del servicio. No estoy seguro de si esta es la mejor manera posible de hacer lo que pide el OP, pero se puede utilizar para lograrlo.

  1. Registrar un manejador onmessage en la página
  2. Envía un mensaje desde el evento de activación o instalación del SW a la página.
  3. Actuar en consecuencia cuando se reciba el mensaje en la página.

Yo mismo he mantenido el número de versión de SW en una variable dentro del SW. Mi SW ha publicado ese número de versión en la página y la página lo ha guardado en el almacenamiento local del navegador. La próxima vez que se cargue la página, SW publica su número de versión actual en la página y el controlador onmessage lo compara con el número de versión almacenado actualmente. Si no son iguales, entonces el SW se ha actualizado a un número de versión que se incluyó en el mssage. Después de eso, he actualizado la copia localStorage del número de versión y he hecho esto y aquello.

Este flujo también se podría hacer al revés: envíe un mensaje desde la página al SW y permita que SW responda algo, luego actúe en consecuencia.

Espero haber podido explicar mis pensamientos claramente :)