Você já ouviu a piada de que, se instalou o ServiceWorker, é hora de mudar o domínio? Agora direi qual é o seu significado e o que fazer se, mesmo assim, decidir que precisa de um PWA.
Nas instruções para o tipo deste ou deste ServiceWorker e trabalhando com ele, quase nenhuma atenção é dada. E tenho certeza de que artigos como este são a primeira coisa que você lê antes de usar. Mas no momento em que, após tais artigos, seu PWA recém-assado finalmente apareceu em produção e os usuários tiveram a oportunidade de adicionar outro ícone à sua área de trabalho, saiba que você passou do ponto sem volta.
Com sua permissão, não irei me alongar na descrição do Service Worker (doravante SW) e como ele funciona. Habré já tem um bom artigo sobre isso . Nem importa qual SW você tem especificamente. Talvez você esteja usando criar-reagir-app , o que significa que a biblioteca Workbox é responsável por SW para você . Talvez você mesmo tenha implementado o SW, com alguma estratégia de cache complicada. A pilha não é realmente importante. A mesma documentação do CRA diz que tudo que você precisa é mudar uma linha e obter todas as delícias de um comportamento semelhante ao de um aplicativo. Você escreveu .register()
e espera o resultado. E você vai conseguir.
Na próxima vez que um cliente insatisfeito lhe pedir para mudar a cor desse botão laranja ou finalmente resolver o bug do foco voador, você se verá em uma situação incrível. Há um hotfix no repositório, o contêiner foi montado e o nginx está distribuindo a versão mais recente com certeza, mas o cliente ainda está insatisfeito por algum motivo. Oh sim, agora somos PWA.
- Atualize a página. Como isso não ajuda? E se CTRL + R?
Então, o que fazer quando a atualização frenética da página não ajuda e o cliente ainda vê o botão laranja falso?
É importante lembrar que o SW tenta se comportar como um aplicativo de desktop.
Vamos lembrar como o aplicativo de desktop se atualiza. Ele baixa o instalador novo, remove a versão antiga e a reinstala. Só depois disso o usuário recebe uma nova versão do aplicativo.
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();
});
Em seguida, precisamos rastrear a aparência do SW em espera. Na minha opinião, é melhor não reagir todas as vezes ao SW com o status de instalação, como está escrito em alguns guias, mas esperar até que o objeto de registro SW retorne verdadeiro no campo waiting
. Isso tornará a atualização mais lenta, mas não acionará seu modal quando o SW for instalado pela primeira vez.
Depois de esperar pelo SW pendente, chamamos uma janela modal na qual o usuário pode confirmar a atualização. Após a confirmação, ligamos skipWaiting()
e forçadamente recarregamos a página conforme descrito acima. Se ocorrer uma falha, a atualização será adiada. O código no meu caso será semelhante a este:
//
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: ' !