Como otimizar aplicativos da Web progressivos: indo além do básico
Publicados: 2022-03-10Os aplicativos da Web progressivos (PWA) ainda estão ganhando popularidade em 2020. Não é uma surpresa, considerando os benefícios de taxas de conversão mais altas, envolvimento do cliente, velocidade de carregamento de página reduzida e custos mais baixos de desenvolvimento e sobrecarga.
Podemos ver empresas respeitadas também tendo sucesso com seus PWAs, como Twitter, Uber, Tinder, Pinterest e Forbes. E todos eles se gabam dos enormes benefícios da implementação dos aplicativos progressivos.
A boa notícia é que desenvolver um PWA não é algo que apenas empresas de grande orçamento podem pagar. Esses aplicativos atendem igualmente a pequenas e médias empresas e não são tão complicados de criar.
Você pode encontrar um guia abrangente para iniciantes para aplicativos da Web progressivos na Smashing Magazine, que se concentra na construção do núcleo de PWAs.
No entanto, vamos dar um passo adiante e aprender a implantar qualidades modernas em PWAs, como funcionalidade offline, otimização baseada em rede, experiência do usuário em vários dispositivos, recursos de SEO e notificações e solicitações não intrusivas. Você também encontrará códigos de exemplo ou referências a guias mais específicos para que possa implementar essas dicas em seu PWA.
Uma visão geral rápida dos aplicativos da Web progressivos (PWA)
Não vamos pular o básico e passar rapidamente pelo coração dos PWAs.
O que é um PWA?
“Progressive Web Apps (PWA) são criados e aprimorados com APIs modernas para fornecer recursos, confiabilidade e instalabilidade aprimorados, alcançando qualquer pessoa, em qualquer lugar, em qualquer dispositivo com uma única base de código.”
— Desenvolvedores do Google
Em outras palavras, os PWAs são sites que os usuários podem usar como aplicativos independentes. Eles são diferentes dos aplicativos nativos principalmente porque os PWAs não exigem instalação e podem ser usados com vários dispositivos — os aplicativos nativos são criados principalmente para dispositivos móveis.
Como funcionam os PWAs?
O núcleo de um PWA consiste em três componentes: um manifesto de aplicativo Web, service workers e um shell de aplicativo. Você pode encontrar instruções detalhadas para construí-las no guia para iniciantes mencionado acima.
Veja o que esses componentes fazem.
Manifesto do aplicativo da Web
O manifesto do aplicativo Web é o núcleo para fazer um site ser executado como um aplicativo autônomo no modo de tela inteira. Você pode definir a aparência do PWA, otimizá-lo para diferentes dispositivos e atribuir um ícone que é exibido após a instalação do aplicativo.
Trabalhadores de serviço
Os service workers habilitam o uso offline do PWA buscando dados em cache ou informando o usuário sobre a ausência de uma conexão com a Internet. Os service workers também recuperam os dados mais recentes assim que a conexão do servidor é restaurada.
Arquitetura do shell do aplicativo
O shell do aplicativo é o que os usuários veem quando acessam um PWA. É o mínimo de HTML, CSS e JavaScript necessário para alimentar a interface do usuário. Ao desenvolver um PWA, você pode armazenar em cache os recursos e ativos do shell do aplicativo no navegador.
Implantando características modernas em seu PWA
Além dos recursos principais, os PWAs modernos adotam características adicionais que conduzem ainda mais seus usuários a uma experiência de usuário mais extraordinária.
Vejamos algumas características modernas específicas de um PWA e aprendamos a adicioná-las ao seu PWA. As qualidades a seguir são consideradas ótimas adições ao PWA básico pelos desenvolvedores do Google.
O aplicativo funciona offline como online
Ao criar seu PWA, você também pode desenvolver uma página offline personalizada como parte do núcleo. No entanto, é muito mais fácil de usar se o seu PWA continuar funcionando mesmo sem uma conexão com a Internet - até um certo ponto em que a conexão se torne necessária. Caso contrário, a experiência do usuário pode ser tão frustrante quanto a provação de Ankita Masand ao pedir um bolo, conforme ela descreve em seu artigo sobre os pontos problemáticos dos PWAs.
Você pode obter uma experiência de usuário mais significativa usando conteúdo em cache, sincronização em segundo plano e telas de esqueleto. Vejamos cada um.
Conteúdo em cache com IndexedDB
IndexedDB
é um sistema de armazenamento NoSQL no navegador que você pode usar para armazenar em cache e recuperar os dados necessários para fazer seu PWA funcionar offline.
No entanto, nem todos os navegadores suportam IndexedDB
, portanto, a primeira coisa que você deseja fazer é verificar se o navegador do usuário o suporta.
if (!('indexedDB' in window)) { console.log('This browser doesn\'t support IndexedDB'); return; }
Depois disso, você pode criar conteúdo em cache com a API IndexedDB. Aqui está um exemplo dos desenvolvedores do Google de como abrir um banco de dados, adicionar um armazenamento de objetos e adicionar um item a esse armazenamento.
var db; var openRequest = indexedDB.open('test_db', 1); openRequest.onupgradeneeded = function(e) { var db = e.target.result; console.log('running onupgradeneeded'); if (!db.objectStoreNames.contains('store')) { var storeOS = db.createObjectStore('store', {keyPath: 'name'}); } }; openRequest.onsuccess = function(e) { console.log('running onsuccess'); db = e.target.result; addItem(); }; openRequest.onerror = function(e) { console.log('onerror!'); console.dir(e); }; function addItem() { var transaction = db.transaction(['store'], 'readwrite'); var store = transaction.objectStore('store'); var item = { name: 'banana', price: '$2.99', description: 'It is a purple banana!', created: new Date().getTime() }; var request = store.add(item); request.onerror = function(e) { console.log('Error', e.target.error.name); }; request.onsuccess = function(e) { console.log('Woot! Did it'); }; }
Sincronização em segundo plano
Se o seu PWA sincronizar dados em segundo plano, o usuário poderá executar ações offline, que serão executadas quando a conexão com a Internet for restaurada. Um exemplo simples é um aplicativo de mensagens. Um usuário pode enviar uma mensagem quando estiver offline sem a necessidade de esperar até que ela seja enviada — a sincronização em segundo plano envia a mensagem automaticamente quando a conexão é restaurada.
Aqui está um exemplo de como desenvolver um recurso de sincronização em segundo plano por Jake Archibald.
// Register your service worker: navigator.serviceWorker.register('/sw.js'); // Then later, request a one-off sync: navigator.serviceWorker.ready.then(function(swRegistration) { return swRegistration.sync.register('myFirstSync'); });
Em seguida, ouça o evento em /sw.js
:
self.addEventListener('sync', function(event) { if (event.tag == 'myFirstSync') { event.waitUntil(doSomeStuff()); } });
Telas de esqueleto
Uma das principais vantagens de usar telas de esqueleto é que os usuários percebem que o aplicativo está funcionando em vez de ficar ocioso. Enquanto o usuário não tem uma conexão, a tela de esqueleto desenha a interface sem conteúdo – que então é preenchida quando a conexão é restaurada.
Code My UI tem alguns excelentes trechos de código disponíveis que você pode usar para criar uma tela de esqueleto para seu PWA.

Otimização com base no uso da rede
Um benefício central de um PWA é que ele fornece uma experiência mais rápida para os usuários. Você pode otimizar ainda mais a velocidade de carregamento fazendo com que o PWA use primeiro a rede de cache, priorizando recursos e use o carregamento adaptável com base na qualidade da rede.
Vejamos como você pode desenvolvê-los para o seu PWA.
Cache primeiro, depois rede
Usar o conteúdo em cache primeiro permite que seu PWA funcione offline e abre caminho para que os usuários acessem o conteúdo mesmo em áreas de baixa cobertura de rede. Você pode fazer isso criando um service worker para armazenar em cache o conteúdo e, em seguida, buscando-o.
Aqui está um exemplo de Jeff Posnick sobre como armazenar em cache HTML estático usando service workers.
self.addEventListener('fetch', event => { if (event.request.mode === 'navigate') { // See /web/fundamentals/getting-started/primers/async-functions // for an async/await primer. event.respondWith(async function() { // Optional: Normalize the incoming URL by removing query parameters. // Instead of https://example.com/page?key=value, // use https://example.com/page when reading and writing to the cache. // For static HTML documents, it's unlikely your query parameters will // affect the HTML returned. But if you do use query parameters that // uniquely determine your HTML, modify this code to retain them. const normalizedUrl = new URL(event.request.url); normalizedUrl.search = ''; // Create promises for both the network response, // and a copy of the response that can be used in the cache. const fetchResponseP = fetch(normalizedUrl); const fetchResponseCloneP = fetchResponseP.then(r => r.clone()); // event.waitUntil() ensures that the service worker is kept alive // long enough to complete the cache update. event.waitUntil(async function() { const cache = await caches.open('my-cache-name'); await cache.put(normalizedUrl, await fetchResponseCloneP); }()); // Prefer the cached response, falling back to the fetch response. return (await caches.match(normalizedUrl)) || fetchResponseP; }()); } });
Priorizando recursos
Por padrão, os PWAs têm melhor desempenho em relação a aplicativos nativos semelhantes devido à sua natureza leve. Além disso, como os PWAs usam o cache do navegador, é possível indicar quais recursos têm prioridade e precisam ser renderizados antes mesmo de serem usados. Isso funciona principalmente com elementos estáticos, pois o conteúdo dinâmico precisa ser atualizado antes de ser buscado.
Você pode especificar a prioridade dos elementos usando a string <link>
no HTML. Você também pode especificar arquivos de servidor de terceiros usando rel=”preconnect”
e rel=”dns-prefetch.”
Maximiliano Firtman dá um exemplo simples disso, priorizando Web Fonts dentro do motor do navegador:
<link rel=”preload” as=”font” href=”font.woff” crossorigin>
Implementando o carregamento adaptável
As velocidades da Internet de WiFi e 4G não são acessíveis em todos os lugares, e os usuários ainda acessam a Internet com conexões 2G e 3G. Como você deseja que seu PWA seja acessível ao maior número possível de pessoas, convém otimizá-lo para funcionar também em velocidades de Internet mais baixas.
Você pode conseguir isso implementando o carregamento adaptativo, que carrega os elementos PWAs com base no tipo de conexão que o usuário possui.


A maneira mais direta é usar a ferramenta Workbox do Google, que inclui vários plugins prontos para estratégias de cache.
Suponha que você queira definir uma estratégia de cache personalizada. Veja como você pode fazer isso como um exemplo de Demian Renzulli e Jeff Posnick:
const adaptiveLoadingPlugin = { requestWillFetch: async ({request}) => { const urlParts = request.url.split('/'); let imageQuality; switch ( navigator && navigator.connection ? navigator.connection.effectiveType : '' ) { //... case '3g': imageQuality = 'q_30'; break; //... } const newUrl = urlParts .splice(urlParts.length - 1, 0, imageQuality) .join('/') .replace('.jpg', '.png'); const newRequest = new Request(newUrl.href, {headers: request.headers}); return newRequest; }, };
Em seguida, passe o plug-in para uma estratégia cacheFirst
contendo uma expressão regular para corresponder a URLs de imagem (por exemplo, /img/
):
workbox.routing.registerRoute( new RegExp('/img/'), workbox.strategies.cacheFirst({ cacheName: 'images', plugins: [ adaptiveLoadingPlugin, workbox.expiration.Plugin({ maxEntries: 50, purgeOnQuotaError: true, }), ], }), );
Excelente experiência do usuário em todas as plataformas
Um excelente PWA funciona perfeitamente em navegadores, dispositivos móveis e tablets. Embora o uso de um dispositivo Android seja a maneira mais popular (com 38,9% de participação de mercado) de acesso à Internet, otimizar seu aplicativo para todas as plataformas faz parte do desenvolvimento das principais funções dos PWAs.
Você pode tomar outras medidas para aumentar a usabilidade e oferecer uma ótima experiência ao usuário, como reduzir o nervosismo quando seu PWA é carregado e garantir que seu PWA funcione com qualquer método de entrada.
Veja como você pode abordar cada um desses aspectos.
Reduzindo o carregamento de conteúdo “inconstante”
Mesmo com Internet de alta velocidade, o conteúdo do site pode mudar durante o carregamento porque os elementos do site são carregados em ordem. Esse efeito é ainda pior com velocidades de conexão mais lentas e prejudica muito a experiência do usuário.
Os elementos mais comuns que fazem com que o conteúdo se desloque durante o carregamento são imagens, pois geralmente são maiores e não são uma prioridade ao carregar o conteúdo. Você pode resolver esse problema com “carregamento lento” usando imagens de espaço reservado menores que você pode priorizar depois que a estrutura HTML for renderizada.
Aqui está um exemplo dos desenvolvedores da Mozilla sobre como você pode adicionar uma imagem leve que é carregada primeiro antes da imagem real em JavaScript:
<img src='data/img/placeholder.png' data-src='data/img/SLUG.jpg' alt='NAME'>
O arquivo app.js
processa os atributos data-src da seguinte forma:
let imagesToLoad = document.querySelectorAll('img[data-src]'); const loadImages = (image) => { image.setAttribute('src', image.getAttribute('data-src')); image.onload = () => { image.removeAttribute('data-src'); }; };
E então crie um loop:
imagesToLoad.forEach((img) => { loadImages(img); });
Você também pode conferir um guia completo na Smashing Magazine sobre como reduzir o salto de conteúdo com outros elementos.
O PWA funciona com qualquer método de entrada
Cobrimos como os PWAs devem funcionar com uma variedade de dispositivos diferentes. Para dar um passo adiante, você também precisa considerar outros métodos de entrada que os usuários podem usar nesses dispositivos, como toque, mouse e caneta.
Adicionar a API Pointer Events ao seu PWA resolve principalmente essa questão. Veja como você pode abordá-lo de acordo com os desenvolvedores do Google.
Primeiro, verifique se o navegador suporta os eventos de ponteiro:
if (window.PointerEvent) { // Yay, we can use pointer events! } else { // Back to mouse and touch events, I guess. }
Em seguida, você pode definir as ações que vários métodos de entrada podem realizar:
switch(ev.pointerType) { case 'mouse': // Do nothing. break; case 'touch': // Allow drag gesture. break; case 'pen': // Also allow drag gesture. break; default: // Getting an empty string means the browser doesn't know // what device type it is. Let's assume mouse and do nothing. break; }
Como a maioria dos navegadores já possui recursos habilitados para toque, você não precisará adicionar mais nada.
Detectável por meio da pesquisa
Um dos principais benefícios do PWA em relação a um aplicativo nativo é que o PWA é um site por natureza e os mecanismos de pesquisa podem indexá-lo. Isso permite que você implante estratégias de SEO para tornar seu conteúdo de PWA mais detectável.
Você pode começar garantindo que cada URL em seu PWA tenha um título exclusivo e descritivo e uma meta descrição, que é a linha de base de qualquer atividade de otimização de SEO.
Vejamos algumas outras etapas que você pode seguir para tornar seu PWA pesquisável.
Analise a encontrabilidade do seu PWA
O Google possui uma excelente ferramenta em seu Search Console que analisa seu site (PWA) e reporta os resultados. Você pode usá-lo para executar uma verificação básica do seu site e descobrir quaisquer pontos fracos que você pode começar a corrigir.
Como alternativa, você pode usar o Lighthouse no navegador Chrome para executar uma auditoria de SEO.
Primeiro, navegue até o URL de destino. Em seguida, pressione Control+Shift+J
(ou Command+Option+J
no Mac) que abre o menu de ferramentas do desenvolvedor. Escolha a guia Lighthouse, marque a caixa de categoria SEO e gere o relatório.

Usar dados estruturados
O mecanismo de pesquisa do Google usa dados estruturados para entender a finalidade do conteúdo em sua página da web.
Dados estruturados são um formato padronizado para fornecer informações sobre uma página e classificar o conteúdo da página; por exemplo, em uma página de receita, quais são os ingredientes, o tempo e a temperatura de cozimento, as calorias e assim por diante.
Antes de começar a codificar, o Google também elaborou uma lista útil de erros comuns de dados estruturados e diretrizes relevantes para corrigi-los. Estudar este material deve fornecer uma boa base do que evitar.
Frederick O'Brien escreveu um excelente guia na Smashing Magazine, Baking Structured Data Into The Design Process , que descreve como construir dados estruturados desde o início.
Notificações amigáveis e solicitações de permissão
Por último, mas não menos importante, você pode aumentar a experiência do usuário otimizando as notificações e solicitações de permissão, para que atendam aos seus usuários, em vez de serem apenas confusos e irritantes.
Embora você geralmente possa confiar no bom senso, existem dicas práticas que você também pode implementar, como criar notificações push não intrusivas e dar ao usuário a opção de cancelar a assinatura de mensagens.
Solicitações sutis de permissão para comunicação
Existem duas maneiras modernas de automatizar a comunicação entre um site e um usuário – chatbots e notificações.
Em um contexto de PWAs, a principal vantagem de um chatbot é que ele não requer permissão do usuário para interagir com o usuário. No entanto, dependendo de qual aplicativo de chatbot você usa, o usuário pode perder a mensagem sutil. As notificações, por outro lado, exigem a permissão do usuário, mas são muito mais visíveis.
Como você pode adicionar um chatbot como um aplicativo de terceiros separado, vamos nos concentrar na criação de uma notificação por push amigável. Caso você precise de um guia sobre como criar uma notificação por push, aqui está um ótimo de Indrek Lasn.
A maneira mais direta de criar uma solicitação de permissão não intrusiva é usando uma solicitação dupla. Isso significa que você inclui uma interação personalizada com seu site sobre a interação padrão do sistema operacional do usuário.
Matt Gaunt oferece ilustrações perfeitas para este efeito com as seguintes imagens.
Aqui está a solicitação de permissão de notificação padrão que não fornece contexto:

E aqui está a interação personalizada adicionada antes da permissão de notificação padrão descrita acima:

Ao adicionar um alerta personalizado antes do padrão do sistema operacional, você pode descrever o objetivo da notificação com mais clareza para o usuário. Isso aumenta a chance de o usuário optar pelas notificações do seu site.
Permitir que o usuário desative as notificações
Para um usuário, desabilitar as notificações push de um site é bastante irritante, independentemente do dispositivo que está usando. Portanto, dar ao usuário a opção de optar por não receber as mensagens ajuda muito em termos de experiência do usuário.
Aqui está um exemplo de Matt Gaunt sobre como implementar uma função de cancelamento de assinatura em seu código e interface do usuário:
Primeiro, defina o listener de cliques do pushButton
:
pushButton.addEventListener('click', function() { pushButton.disabled = true; if (isSubscribed) { unsubscribeUser(); } else { subscribeUser(); } });
Em seguida, adicione uma nova função:
function unsubscribeUser() { swRegistration.pushManager.getSubscription() .then(function(subscription) { if (subscription) { // TODO: Tell application server to delete subscription return subscription.unsubscribe(); } }) .catch(function(error) { console.log('Error unsubscribing', error); }) .then(function() { updateSubscriptionOnServer(null); console.log('User is unsubscribed.'); isSubscribed = false; updateBtn(); }); }
Veja como fica no console depois de implementar com sucesso o botão de inscrição para desativar as notificações, se o usuário escolher.

Console.log
de uma função de ativação/desativação bem-sucedida de notificações por Matt Gaunt. (Visualização grande)Conclusão
Os PWAs podem ser muito poderosos para aumentar o tráfego do seu site e expandir a experiência do usuário. Para otimizar ainda mais seu PWA, você pode usar essas soluções modernas descritas neste artigo para aprimorar o desempenho e a funcionalidade.
Você também não precisa implementar tudo de uma vez. Sinta-se à vontade para escolher as opções mais relevantes, pois cada uma dessas sugestões ajuda você a aprimorar seu PWA.
Recursos adicionais
- Treinamento Progressive Web Apps do Google
- Aplicativos da Web progressivos por web.dev
- Aplicativos web progressivos (PWAs) da Mozilla