Atualizar

Você publicou seu PWA: alguns usuários o utilizam pelo navegador, outros o instalam nos dispositivos. Ao atualizar o app, é importante aplicar as práticas recomendadas para evitar armadilhas.

Você pode atualizar:

  • Dados de apps.
  • Recursos já armazenados em cache nos dispositivos.
  • O arquivo do service worker ou as dependências dele.
  • Metadados do manifesto.

Confira as práticas recomendadas para cada um desses elementos.

Atualização de dados

Para atualizar dados, como aqueles armazenados no IndexedDB, você pode usar ferramentas como Fetch, WebRTC ou API WebSockets. Se o app for compatível com recursos off-line, mantenha os dados compatíveis com os recursos atualizados também.

Em navegadores compatíveis, há opções para sincronizar dados, não apenas quando o usuário abre o PWA, mas também em segundo plano. Essas opções são:

  • Sincronização em segundo plano: salva as solicitações que falharam e as repete usando a sincronização do service worker.
  • Sincronização periódica em segundo plano na Web: sincroniza dados periodicamente em segundo plano, em momentos específicos, para permitir que o app forneça dados atualizados mesmo que o usuário ainda não o tenha aberto.
  • Busca em segundo plano: faz o download de arquivos grandes, mesmo quando o PWA está fechado.
  • Push na Web: envia uma mensagem do servidor que ativa o service worker e notifica o usuário. Isso geralmente é chamado de "notificação push". Essa API requer a permissão do usuário.

Todas essas APIs são executadas no contexto do service worker. No momento, elas estão disponíveis apenas em navegadores baseados no Chromium, no Android e em sistemas operacionais de computadores. Quando você usa uma dessas APIs, pode executar o código na linha de execução do service worker. Por exemplo, para fazer o download de dados do seu servidor e atualizar os dados do IndexedDB.

Atualizando recursos

A atualização inclui qualquer mudança nos arquivos usados para renderizar a interface do app, como HTML, CSS, JavaScript e imagens. Por exemplo, uma mudança na lógica do aplicativo, uma imagem que faz parte da sua interface ou uma folha de estilo CSS.

Atualizar padrões

Veja alguns padrões comuns para processar atualizações de apps, mas é possível personalizar o processo de acordo com suas próprias necessidades:

  • Atualização completa: todas as alterações, mesmo as menores, acionam a substituição de todo o conteúdo do cache. Esse padrão imita como os apps específicos do dispositivo lidam com as atualizações, o que consome mais largura de banda e mais tempo.
  • Atualização de recursos alterados: somente os recursos que foram alterados desde a última atualização são substituídos em cache. Geralmente, ele é implementado usando uma biblioteca, como o Workbox. Ela envolve a criação de uma lista de arquivos armazenados em cache, uma representação em hash do arquivo e carimbos de data/hora. Com essas informações, o service worker compara essa lista com os recursos armazenados em cache e decide quais deles atualizar.
  • Atualização de recursos individuais: cada recurso é atualizado individualmente quando há alterações. A estratégia "desfazer ao revalidar" descrita no capítulo de veiculação é um exemplo de atualização de recursos individualmente.

Quando atualizar

Outra prática recomendada é encontrar um bom momento para verificar se há atualizações e aplicá-las. Veja algumas opções:

  • Quando o service worker desperta. Não há evento para detectar por enquanto, mas o navegador vai executar qualquer código no escopo global do service worker quando for ativado.
  • Na janela principal do PWA, depois que o navegador carregou a página, para evitar que o app carregue mais lentamente.
  • Quando eventos em segundo plano são acionados, por exemplo, quando o PWA recebe uma notificação push ou uma sincronização em segundo plano é acionada. É possível atualizar o cache. Assim, os usuários terão a nova versão do recurso na próxima vez que abrirem o app.

Atualizações ao vivo

Você também pode escolher se quer aplicar uma atualização quando o app estiver aberto (ativo) ou fechado. Com a abordagem fechada, mesmo que o app tenha feito o download de novos recursos, ele não vai fazer mudanças e vai usar as novas versões no próximo carregamento.

Uma atualização em tempo real significa que, assim que o recurso for atualizado no cache, o PWA vai substituir o recurso no carregamento atual. Essa é uma tarefa complexa que não é abordada neste curso. Algumas ferramentas que ajudam a implementar essa atualização são o livereload-js e a API CSSStyleSheet.replace() de atualização de recursos do CSS.

Como atualizar o service worker

O navegador aciona um algoritmo de atualização quando o service worker ou as dependências dele mudam. O navegador detecta atualizações usando uma comparação byte a byte entre os arquivos armazenados em cache e os recursos provenientes da rede.

Em seguida, o navegador tenta instalar a nova versão do service worker, e o novo service worker estará no estado waiting, como descrito no capítulo Service workers. A nova instalação vai executar o evento install para o novo service worker. Se você estiver armazenando recursos em cache nesse manipulador de eventos, os recursos também serão armazenados em cache novamente.

Como detectar mudanças no service worker

Para detectar que um novo service worker está pronto e instalado, usamos o evento updatefound do registro dele. Este evento é disparado quando o novo service worker começa a instalar. É preciso esperar até que o estado mude para installed com o evento statechange. Confira o seguinte:

async function detectSWUpdate() {
  const registration = await navigator.serviceWorker.ready;

  registration.addEventListener("updatefound", event => {
    const newSW = registration.installing;
    newSW.addEventListener("statechange", event => {
      if (newSW.state == "installed") {
         // New service worker is installed, but waiting activation
      }
    });
  })
}

Forçar substituição

O novo service worker será instalado, mas vai aguardar a ativação por padrão. A espera impede que o novo service worker assuma clientes antigos que possam não ser compatíveis com a nova versão.

Mesmo que não seja recomendado, o novo service worker pode pular esse período de espera e iniciar a ativação imediatamente.

self.addEventListener("install", event => {
   // forces a service worker to activate immediately
   self.skipWaiting();
  });

self.addEventListener("activate", event => {
  // when this SW becomes activated, we claim all the opened clients
  // they can be standalone PWA windows or browser tabs
  event.waitUntil(clients.claim());
});

O evento controllerchange é disparado quando o service worker que controla a página atual muda. Por exemplo, um novo worker ignorou a espera e se tornou o novo worker ativo.

navigator.serviceWorker.addEventListener("controllerchange", event => {
   // The service worker controller has changed
 });

Atualizar metadados

Também é possível atualizar os metadados do app, que são definidos principalmente no manifesto do app da Web. Por exemplo, atualize o ícone, o nome ou o URL de início ou adicione um novo recurso, como atalhos de apps. Mas o que acontece com todos os usuários que já instalaram o app com o ícone antigo nos dispositivos? Como e quando eles obtêm a versão atualizada?

A resposta depende da plataforma. Vamos ver as opções disponíveis.

Safari nos navegadores iOS, iPadOS e Android

Nessas plataformas, a única maneira de conseguir os novos metadados do manifesto é reinstalar o app pelo navegador.

Google Chrome no Android com WebAPK

Quando o usuário instalar o PWA no Android usando o Google Chrome com o WebAPK ativado (a maioria das instalações do PWA do Chrome), a atualização será detectada e aplicada com base em um algoritmo. Confira os detalhes neste artigo sobre atualizações do manifesto.

Algumas observações adicionais sobre o processo:

Se o usuário não abrir o PWA, o WebAPK não será atualizado. Se o servidor não responder com o arquivo de manifesto (houver um erro 404), o Chrome não verificará se há atualizações por um período mínimo de 30 dias, mesmo que o usuário abra o PWA.

Acesse about:webapks no Chrome para Android para conferir o status da flag "Precisa de atualização" e solicitar uma atualização. No capítulo Ferramentas e depuração, leia mais sobre essa ferramenta.

Samsung Internet no Android com WebAPK

O processo é semelhante à versão do Chrome. Nesse caso, se o manifesto do PWA exigir uma atualização, nas próximas 24 horas, o WebAPK será atualizado no Wi-Fi depois da criação do WebAPK atualizado.

Google Chrome e Microsoft Edge no computador

Em dispositivos desktop, quando o PWA é iniciado, o navegador determina a última vez que verificou o manifesto local em busca de mudanças. Se o manifesto não tiver sido analisado desde a última inicialização do navegador ou não tiver sido verificado nas últimas 24 horas, o navegador fará uma solicitação de rede para o manifesto e o comparará com a cópia local.

Quando as propriedades selecionadas forem atualizadas, uma atualização vai ser acionada depois que todas as janelas forem fechadas.

Como alertar o usuário

Algumas estratégias de atualização precisam ser recarregadas ou uma nova navegação por parte dos clientes. Informe ao usuário que há uma atualização aguardando, mas ofereça a ele a chance de atualizar a página quando for melhor para ele.

Para informar o usuário, existem estas opções:

  • Use o DOM ou a API Canvas para renderizar um aviso na tela.
  • Use a API Web Notifications. Essa API faz parte da permissão push para gerar uma notificação no sistema operacional. Será necessário solicitar permissão de push da Web para usá-lo, mesmo que você não use o protocolo de mensagens push do seu servidor. Essa é a única opção que temos se o PWA não for aberto.
  • Use a API Badging para mostrar que as atualizações estão disponíveis no ícone instalado do PWA.

Uma notificação de atualização é mostrada no DOM..

Saiba mais sobre a API Badging

A API Badging permite marcar o ícone do PWA com um número ou ponto de selo em navegadores compatíveis. Um ponto de selo é uma pequena marca dentro do ícone de instalação que indica que algo está esperando dentro do app.

Exemplo de Twitter com oito notificações e outro app mostrando um selo de sinalização.

É necessário chamar setAppBadge(count) no objeto navigator para definir um número de selo. Faça isso na janela ou no contexto do service worker quando houver uma atualização para alertar o usuário.

let unreadCount = 125;
navigator.setAppBadge(unreadCount);

Para limpar o selo, chame clearAppBadge() no mesmo objeto:

navigator.clearAppBadge();

Recursos