Arquitetura

O design do seu aplicativo para aproveitar ao máximo a tecnologia que torna os PWAs confiáveis, instaláveis e capazes começa com a compreensão do aplicativo e das restrições dele e a escolha de uma arquitetura adequada para ambos.

SPA x MPA

Atualmente, há dois padrões de arquitetura principais no desenvolvimento da Web: aplicativos de página única, ou SPAs, e aplicativos de várias páginas, ou MPAs.

Os apps de página única são definidos por ter o controle do JavaScript do lado do cliente na maior parte ou em toda a renderização HTML de uma página com base nos dados recuperados ou fornecidos ao app. O app substitui a navegação integrada do navegador, substituindo-a pela funcionalidade de roteamento e gerenciamento de visualizações.

Os apps com várias páginas geralmente têm HTML pré-renderizado enviado diretamente ao navegador, muitas vezes aprimorado com JavaScript do lado do cliente depois que o navegador termina de carregar o HTML e depende dos mecanismos de navegação integrados do navegador para mostrar as visualizações seguintes.

Ambas as arquiteturas podem ser usadas para criar PWAs.

Cada uma tem vantagens e desvantagens, e selecionar o certo para seu caso de uso e contexto é fundamental para fornecer uma experiência rápida e confiável para os usuários.

Apps de página única

Prós
  • Principalmente atualizações atômicas na página.
  • Dependências do lado do cliente carregadas na inicialização.
  • Os carregamentos subsequentes são rápidos devido ao uso do cache.
Contras
  • Custo de carregamento inicial alto.
  • A performance depende do hardware do dispositivo e da conexão de rede.
  • É necessária uma complexidade adicional do app.

Os apps de página única são uma boa arquitetura se:

  • A interação do usuário é centrada principalmente em atualizações atômicas de dados interconectados exibidos na mesma página, por exemplo, um painel de dados em tempo real ou um aplicativo de edição de vídeo.
  • Seu aplicativo tem dependências de inicialização apenas do lado do cliente, por exemplo, um provedor de autenticação terceirizado com um custo de inicialização incrivelmente alto.
  • Os dados necessários para carregar uma visualização dependem de um contexto específico do lado do cliente, por exemplo, exibir controles de um hardware conectado.
  • O app é pequeno e simples o suficiente para que o tamanho e a complexidade não tenham impacto nos contras listados acima.

Os SPAs podem não ser uma boa escolha de arquitetura se:

  • O desempenho do carregamento inicial é essencial. Os SPAs geralmente precisam carregar mais JavaScript para determinar o que carregar e como exibir essas informações. O tempo de análise e execução desse JavaScript, combinado com a recuperação de conteúdo, é mais lento do que o envio de HTML renderizado.
  • Seu app é executado principalmente em dispositivos de baixa ou média potência. Como as SPAs dependem do JavaScript para renderização, a experiência do usuário depende muito mais da capacidade do dispositivo específico do que em uma MPA.

Como as SPAs precisam substituir a navegação integrada do navegador pelo roteamento, elas exigem um nível mínimo de complexidade para atualizar a visualização atual de maneira eficiente, gerenciar mudanças de navegação e limpar visualizações anteriores que seriam processadas pelo navegador, o que as torna mais difíceis de manter e mais pesadas para o dispositivo do usuário.

Apps de várias páginas

Prós
  • Principalmente atualizações de página inteira.
  • A velocidade de renderização inicial é fundamental.
  • A criação de scripts do lado do cliente pode ser uma melhoria.
Contras
  • As visualizações secundárias exigem outra chamada de servidor.
  • O contexto não é transferido entre visualizações.
  • Requer um servidor ou pré-renderização.

Os aplicativos de várias páginas são uma boa opção de arquitetura se:

  • A interação do usuário é centrada principalmente em visualizações de um único dado com dados opcionais baseados em contexto, por exemplo, um app de notícias ou e-commerce.
  • A velocidade de renderização inicial é fundamental, porque enviar HTML já renderizado para o navegador é mais rápido do que montá-lo a partir de uma solicitação de dados após carregar, analisar e executar uma alternativa baseada em JavaScript.
  • Interatividade ou contexto do lado do cliente podem ser incluídos como um aprimoramento após o carregamento inicial, por exemplo, colocar um perfil em uma página renderizada ou adicionar componentes secundários dependentes de contexto do lado do cliente.

As MPAs podem não ser uma boa escolha de arquitetura se:

  • Fazer o download, analisar e executar novamente o JavaScript ou CSS é muito caro. Esse problema é mitigado em PWA com service workers.
  • O contexto do lado do cliente, como a localização do usuário, não é transferido perfeitamente entre as visualizações, e a obtenção desse contexto novamente pode ser cara. Ele precisa ser capturado e recuperado ou solicitado novamente entre as visualizações.

Porque as visualizações individuais precisam ser renderizadas dinamicamente por um servidor ou pré-renderizadas antes do acesso, o que pode limitar a hospedagem ou aumentar a complexidade dos dados.

Qual escolher?

Mesmo com essas vantagens e desvantagens, as duas arquiteturas são válidas para criar sua PWA. Você pode até mesmo misturá-las para diferentes partes do app, dependendo das necessidades dele. Por exemplo, fazer com que as páginas "Detalhes do app" sigam uma arquitetura MPA e o fluxo de finalização de compra siga uma arquitetura SPA.

Independentemente da escolha, a próxima etapa é entender como usar os service workers para oferecer a melhor experiência.

O poder do service worker

O worker de serviço tem muito poder além do roteamento básico e do envio de respostas em cache e de rede. Podemos criar algoritmos complexos que podem melhorar a experiência e o desempenho do usuário.

Inclui service worker (SWI)

Um padrão emergente para o uso de service workers como parte integral da arquitetura de um site é o service worker inclui (SWI). O SWI divide recursos individuais, normalmente uma página HTML, em partes com base nas necessidades de armazenamento em cache. Depois, ele os reúne no service worker para melhorar a consistência, o desempenho e a confiabilidade, além de reduzir o tamanho do cache. Um site com cabeçalho global, área de conteúdo, barra lateral e rodapé.

Esta imagem é um exemplo de página da Web. Ele tem cinco seções diferentes que dividem a página em:

  • Layout geral.
  • Cabeçalho global (barra escura de cima).
  • Área de conteúdo (linhas e imagem à esquerda do meio).
  • Barra lateral (barra alta média escura no meio à direita).
  • Rodapé (barra inferior escura).

Layout geral

O layout geral não muda com frequência e não tem dependências. É um bom candidato para pré-cache.

O cabeçalho e o rodapé globais contêm itens como o menu superior e o rodapé do site, além de apresentar um desafio específico: se a página for armazenada em cache como um todo, isso poderá mudar entre os carregamentos de página, dependendo de quando uma determinada página foi armazenada.

Separá-los e armazená-los em cache, independentemente do conteúdo, você garante que os usuários sempre recebam a mesma versão, independentemente de quando estiverem armazenados em cache. Como elas são atualizadas com pouca frequência, também são boas candidatas para pré-cache. No entanto, eles têm uma dependência: o CSS e o JavaScript do site.

CSS e JavaScript

O ideal é que o CSS e o JavaScript do site sejam armazenados em cache com uma estratégia de revalidação para permitir atualizações incrementais sem precisar atualizar o worker do serviço, como é o caso dos recursos pré-armazenados em cache. No entanto, elas também precisam ser mantidas em uma versão mínima sempre que o worker de serviço for atualizado com um novo cabeçalho ou rodapé global. Por isso, o cache também precisa ser atualizado com a versão mais recente dos recursos quando o service worker é instalado.

Área de conteúdo

Em seguida, temos a área de conteúdo. Dependendo da frequência das atualizações, usar a rede primeiro ou ficar desatualizado durante a revalidação é uma boa estratégia. As imagens devem ser armazenadas em cache primeiro com uma estratégia de cache, como já discutido anteriormente.

Por fim, supondo que o conteúdo da barra lateral tenha conteúdo secundário, como tags e itens relacionados, não é crítico o suficiente para extrair da rede. Uma estratégia desatualizada ao revalidar funciona para isso.

Depois de tudo isso, você pode pensar que só é possível fazer esse tipo de armazenamento em cache por seção em apps de página única. No entanto, ao adotar padrões inspirados em inclusões do lado do servidor ou inclusões do lado do servidor no service worker, com alguns recursos avançados, é possível fazer isso em qualquer arquitetura.

Sua vez de tentar

Você pode testar os recursos do worker de serviço com o próximo codelab:

Respostas de streaming

A página anterior poderia ser criada usando o modelo de shell do app no ambiente dos SPA, onde o shell do app é armazenado em cache, depois veiculado e o conteúdo carregado no lado do cliente. Com a introdução e a ampla disponibilidade da API Streams, tanto o shell do app quanto o conteúdo podem ser combinados no service worker e transmitidos para o navegador, oferecendo a flexibilidade de armazenamento em cache do shell do app com a velocidade das MPAs.

Isso acontece porque:

  • Os streams podem ser criados de forma assíncrona, permitindo que diferentes partes de um stream venham de outras origens.
  • O solicitante de um stream pode começar a trabalhar na resposta assim que o primeiro bloco de dados estiver disponível, em vez de esperar que o item inteiro seja concluído.
  • Os analisadores otimizados para streaming, incluindo o navegador, podem mostrar progressivamente o conteúdo do stream antes que ele seja concluído, acelerando a performance percebida da resposta.

Graças a essas três propriedades dos streams, as arquiteturas criadas em torno do streaming geralmente têm uma performance percebida mais rápida do que as que não são.

Trabalhar com a API Streams pode ser desafiador, porque ela é complexa e de baixo nível. Felizmente, há um módulo Workbox que pode ajudar a configurar respostas de streaming para seus workers de serviço.

Domínios, origens e escopo da PWA

Os workers da Web, incluindo service workers, armazenamento e até mesmo uma janela de PWA instalada, são governados por um dos mecanismos de segurança mais importantes da Web: a política de mesma origem. Na mesma origem, as permissões são concedidas, os dados podem ser compartilhados e o service worker pode se comunicar com diferentes clientes. Fora da mesma origem, as permissões não são concedidas automaticamente, e os dados são isolados e não acessíveis entre origens diferentes.

Política de mesma origem

Dois URLs são definidos como tendo a origem exata se o protocolo, a porta e o host forem os mesmos.

Por exemplo: https://squoosh.app e https://squoosh.app/v2 têm a mesma origem, mas http://squoosh.app, https://squoosh.com, https://app.squoosh.app e https://squoosh.app:8080 estão em origens diferentes. Consulte a referência da MDN sobre a política de mesma origem para mais informações e exemplos.

Mudar subdomínios não é a única maneira de alterar um host. Cada host é composto por um domínio de nível superior (TLD), um domínio de nível secundário (SLD) e zero ou mais identificadores (às vezes chamados de subdomínios), separados por pontos e lidos da direita para a esquerda em um URL. Uma mudança em qualquer um dos itens resulta em um host diferente.

No módulo de gerenciamento de janelas, já vimos como o navegador no app aparece quando um usuário navega para uma origem diferente de um PWA instalado.

Esse navegador no app vai aparecer mesmo que os sites tenham o mesmo TLD e SLD, mas com rótulos diferentes, já que são considerados origens diferentes.

Um dos principais aspectos de uma origem em um contexto de navegação na Web é como o armazenamento e as permissões funcionam. Uma origem compartilha muitos recursos entre todo o conteúdo e as PWAs, incluindo:

  • Quota de armazenamento e dados (IndexedDB, cookies, armazenamento da Web, armazenamento em cache).
  • Registros de service workers.
  • Permissões concedidas ou negadas (como push da Web, geolocalização, sensores).
  • Registros de push da Web.

Quando você muda de uma origem para outra, todo o acesso anterior é revogado. Portanto, as permissões precisam ser concedidas novamente, e o PWA não pode acessar todos os dados salvos no armazenamento.

Recursos