Arquitetura de Progressive Web Apps: Padrões de Service Worker em JavaScript | MLOG | MLOG

4. Apenas Rede (Network-Only)

A estratégia de apenas rede obtém sempre os recursos da rede, contornando completamente o cache. Esta estratégia é usada quando precisa absolutamente da versão mais recente de um recurso e o cache não é desejado.

Exemplo:

            
self.addEventListener('fetch', event => {
  event.respondWith(
    fetch(event.request)
  );
});

            

5. Stale-While-Revalidate

A estratégia stale-while-revalidate serve o recurso em cache imediatamente, enquanto simultaneamente busca a versão mais recente da rede. Assim que o pedido de rede é concluído, o cache é atualizado com a nova versão. Esta estratégia proporciona uma resposta inicial rápida, garantindo que o utilizador acaba por receber o conteúdo mais atualizado. É uma estratégia útil para conteúdo não crítico que beneficia mais da velocidade do que da frescura absoluta.

Exemplo:

            
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request)
      .then(response => {
        const fetchPromise = fetch(event.request).then(networkResponse => {
          caches.open('my-cache').then(cache => {
            cache.put(event.request, networkResponse.clone());
            return networkResponse;
          });
        });
        return response || fetchPromise;
      })
  );
});

            

6. Cache, depois Rede

Semelhante à stale-while-revalidate, mas sem o retorno imediato do recurso em cache. Verifica primeiro o cache, e só se o recurso estiver presente é que o pedido de rede prosseguirá em segundo plano para atualizar o cache.

Escolher a Estratégia de Cache Certa

A estratégia de cache ótima depende dos requisitos específicos da sua aplicação. Considere fatores como:

Ao selecionar cuidadosamente as estratégias de cache apropriadas, pode melhorar significativamente o desempenho e a experiência do utilizador do seu PWA, mesmo em ambientes offline. Ferramentas como o Workbox ([https://developers.google.com/web/tools/workbox](https://developers.google.com/web/tools/workbox)) podem simplificar a implementação destas estratégias.

Sincronização em Segundo Plano: Lidar com Mutações Offline

A sincronização em segundo plano permite que o seu PWA realize tarefas em segundo plano, mesmo quando o utilizador está offline. Isto é particularmente útil para lidar com submissões de formulários, atualizações de dados e outras operações que requerem conectividade de rede. A API `BackgroundSyncManager` permite-lhe registar tarefas que serão executadas quando a rede estiver disponível.

Registar uma Tarefa de Sincronização em Segundo Plano

Para registar uma tarefa de sincronização em segundo plano, precisa de usar o método `register` do `BackgroundSyncManager`. Este método recebe um nome de etiqueta único como argumento. O nome da etiqueta identifica a tarefa específica a ser realizada.

Exemplo:

            
self.addEventListener('sync', event => {
  if (event.tag === 'my-sync-task') {
    event.waitUntil(doSomeWork());
  }
});

            

Lidar com o Evento de Sincronização (Sync)

Quando o navegador deteta conectividade de rede, ele envia um evento `sync` para o service worker. Pode escutar este evento e realizar as ações necessárias, como enviar dados para o servidor.

Exemplo:

            
async function doSomeWork() {
  // Recuperar dados do IndexedDB
  const data = await getDataFromIndexedDB();

  // Enviar dados para o servidor
  try {
    const response = await fetch('/api/sync', {
      method: 'POST',
      body: JSON.stringify(data),
      headers: {
        'Content-Type': 'application/json'
      }
    });

    if (response.ok) {
      // Limpar os dados do IndexedDB
      await clearDataFromIndexedDB();
    } else {
      // Lidar com erros
      console.error('Sincronização falhou:', response.status);
      throw new Error('Sincronização falhou');
    }
  } catch (error) {
    // Lidar com erros de rede
    console.error('Erro de rede:', error);
    throw error;
  }
}

            

Exemplo: Submissão de Formulário Offline

Imagine um cenário onde um utilizador preenche um formulário enquanto está offline. O service worker pode armazenar os dados do formulário no IndexedDB e registar uma tarefa de sincronização em segundo plano. Quando a rede estiver disponível, o service worker irá recuperar os dados do formulário do IndexedDB e submetê-los ao servidor.

  1. O utilizador preenche o formulário e clica em submeter enquanto está offline.
  2. Os dados do formulário são armazenados no IndexedDB.
  3. Uma tarefa de sincronização em segundo plano é registada com uma etiqueta única (por exemplo, `form-submission`).
  4. Quando a rede está disponível, o evento `sync` é acionado.
  5. O service worker recupera os dados do formulário do IndexedDB e submete-os ao servidor.
  6. Se a submissão for bem-sucedida, os dados do formulário são removidos do IndexedDB.

Notificações Push: Envolver os Utilizadores com Atualizações Oportunas

As notificações push permitem que o seu PWA envie atualizações e mensagens oportunas aos utilizadores, mesmo quando a aplicação não está a ser executada ativamente no navegador. Isto pode melhorar significativamente o envolvimento e a retenção do utilizador. A API Push e a API Notifications trabalham em conjunto para entregar notificações push.

Subscrever Notificações Push

Para receber notificações push, os utilizadores devem primeiro conceder permissão ao seu PWA. Pode usar a API `PushManager` para subscrever os utilizadores a notificações push.

Exemplo:

            
navigator.serviceWorker.ready.then(registration => {
  registration.pushManager.subscribe({
    userVisibleOnly: true,
    applicationServerKey: 'SUA_CHAVE_VAPID_PUBLICA'
  })
  .then(subscription => {
    // Enviar detalhes da subscrição para o seu servidor
    sendSubscriptionToServer(subscription);
  })
  .catch(error => {
    console.error('Falha ao subscrever:', error);
  });
});

            

Importante: Substitua `SUA_CHAVE_VAPID_PUBLICA` pela sua chave VAPID (Voluntary Application Server Identification) real. As chaves VAPID são usadas para identificar o seu servidor de aplicação e garantir que as notificações push são enviadas de forma segura.

Lidar com Notificações Push

Quando uma notificação push é recebida, o service worker envia um evento `push`. Pode escutar este evento e exibir a notificação ao utilizador.

Exemplo:

            
self.addEventListener('push', event => {
  const payload = event.data ? event.data.text() : 'Sem conteúdo';

  event.waitUntil(
    self.registration.showNotification('Meu PWA', {
      body: payload,
      icon: 'icon.png'
    })
  );
});

            

Personalizar Notificações Push

A API Notifications permite-lhe personalizar a aparência e o comportamento das notificações push. Pode especificar o título, corpo, ícone, selo e outras opções.

Exemplo:

            
self.addEventListener('push', event => {
  const data = event.data.json();
  const title = data.title || 'Meu PWA';
  const options = {
    body: data.body || 'Sem mensagem',
    icon: data.icon || 'icon.png',
    badge: data.badge || 'badge.png',
    vibrate: [200, 100, 200],
    data: { // Dados personalizados que pode aceder quando o utilizador clica na notificação
      url: data.url || '/'
    },
    actions: [
      {action: 'explore', title: 'Explorar este novo mundo',
        icon: 'images/checkmark.png'},
      {action: 'close', title: 'Fechar',
        icon: 'images/xmark.png'},
    ]
  };

  event.waitUntil(self.registration.showNotification(title, options));
});


self.addEventListener('notificationclick', function(event) {
  event.notification.close();

  // Verificar se o utilizador clicou numa ação.
  if (event.action === 'explore') {
    clients.openWindow(event.notification.data.url);
  } else {
    // Ação padrão: abrir a aplicação.
    clients.openWindow('/');
  }
});

            

Exemplo: Alerta de Notícias

Uma aplicação de notícias pode usar notificações push para alertar os utilizadores sobre notícias de última hora. Quando um novo artigo é publicado, o servidor envia uma notificação push para o dispositivo do utilizador, exibindo um breve resumo do artigo. O utilizador pode então clicar na notificação para abrir o artigo completo no PWA.

Padrões Avançados de Service Worker

1. Análise Offline

Acompanhe o comportamento do utilizador mesmo quando ele está offline, armazenando dados de análise localmente e enviando-os para o servidor quando a rede estiver disponível. Isto pode ser alcançado usando IndexedDB e Background Sync.

2. Controlo de Versão e Atualização

Implemente uma estratégia robusta de controlo de versão para o seu service worker para garantir que os utilizadores recebam sempre as últimas atualizações sem interromper a sua experiência. Use técnicas de "cache busting" para invalidar recursos antigos em cache.

3. Service Workers Modulares

Organize o código do seu service worker em módulos para melhorar a manutenibilidade e a legibilidade. Use módulos JavaScript (ESM) ou um empacotador de módulos como Webpack ou Rollup.

4. Cache Dinâmico

Coloque recursos em cache dinamicamente com base nas interações do utilizador e nos padrões de uso. Isto pode ajudar a otimizar o tamanho do cache e a melhorar o desempenho.

Melhores Práticas para o Desenvolvimento de Service Workers

Conclusão

Os service workers JavaScript são ferramentas poderosas para construir PWAs robustos, de alto desempenho e envolventes. Ao compreender o ciclo de vida do service worker e implementar estratégias de cache apropriadas, sincronização em segundo plano e notificações push, pode criar experiências de utilizador excecionais, mesmo em ambientes offline. Este artigo explorou os principais padrões e melhores práticas de service worker para o guiar na construção de PWAs de sucesso para um público global. À medida que a web continua a evoluir, os service workers desempenharão um papel cada vez mais importante na definição do futuro do desenvolvimento web.

Lembre-se de adaptar estes padrões aos requisitos específicos da sua aplicação e priorize sempre a experiência do utilizador. Ao abraçar o poder dos service workers, pode criar PWAs que não são apenas funcionais, mas também agradáveis de usar, independentemente da localização ou da ligação de rede do utilizador.

Recursos Adicionais: