Deixe o PWA mais parecido com um app

Faça seu Progressive Web App não parecer um site, mas sim um app "real"

Ao jogar bingo de palavras da moda do Progressive Web App, é seguro definir como "os PWAs são apenas sites". A documentação do PWA da Microsoft concorda e declaramos neste mesmo site. Até mesmo os indicadores do PWA, Frances Berriman e Alex Russell, também escreveram. Sim, os PWAs são apenas sites, mas eles também são muito mais do que isso. Se bem feito, um PWA não vai parecer um site, mas sim um app "real". Mas o que significa se parecer com um app de verdade?

Para responder a essa pergunta, vou usar o app Podcasts da Apple como exemplo. Ele está disponível para macOS no computador e iOS (e iPadOS, respectivamente) para dispositivos móveis. Embora o Google Podcasts seja um aplicativo de mídia, as ideias principais que ilustramos com a ajuda dele também podem ser aplicadas a outras categorias de apps.

Um iPhone e um MacBook lado a lado executando o aplicativo Podcasts lado a lado.
Apple Podcasts no iPhone e no macOS (Fonte).

Pode funcionar off-line

Se você parar para pensar nos aplicativos específicos da plataforma que possui em seu celular ou computador desktop, uma coisa se destaca claramente: você nunca recebe nada. No app Podcasts, mesmo off-line, sempre há algo. Quando não há conexão de rede, o aplicativo naturalmente ainda é aberto. A seção Gráficos principais não mostra nenhum conteúdo, em vez disso, ela retorna a mensagem Não é possível se conectar no momento pareada com um botão Tentar novamente. Pode não ser a experiência mais acolhedora, mas eu ganho algo.

O app Podcasts mostrando uma mensagem de informação "Não é possível se conectar no momento" quando não há conexão de rede disponível.
App Podcasts sem conexão de rede.

O app Podcasts segue o chamado modelo de shell do app. Todo o conteúdo estático necessário para mostrar o app principal é armazenado em cache localmente, incluindo imagens decorativas, como os ícones do menu à esquerda e os ícones da interface do player principal. O conteúdo dinâmico, como os dados dos Mais pesquisados, é carregado somente sob demanda, com conteúdo substituto armazenado em cache localmente caso o carregamento falhe. Leia o artigo O modelo de shell dos apps para saber como aplicar esse modelo de arquitetura ao seu app da Web.

Conteúdo off-line disponível e mídia reproduzível

Enquanto estiver off-line, pela gaveta esquerda, ainda posso navegar até a seção Downloads e aproveitar episódios de podcast salvos que estão prontos para serem reproduzidos e exibidos com todos os metadados, como arte e descrições.

App Podcasts com um episódio transferido por download de um podcast tocando.
Você pode assistir os episódios de podcasts salvos mesmo sem rede.

O conteúdo de mídia salvo anteriormente pode ser disponibilizado no cache, por exemplo, usando o roteiro Exibir áudio e vídeo em cache da biblioteca Workbox. Outros conteúdos podem ser armazenados em cache ou no IndexedDB. Leia o artigo Armazenamento para a Web para saber todos os detalhes e saber quando usar qual tecnologia de armazenamento. Se você tiver dados que precisam ser armazenados com persistência sem o risco de serem limpos quando a quantidade de memória disponível fica baixa, use a API Persistent Storage.

Download proativo em segundo plano

Quando eu estiver on-line de novo, posso pesquisar conteúdo com uma consulta como http 203 e, quando eu decidir me inscrever no resultado da pesquisa, o podcast HTTP 203, o episódio mais recente da série será transferido imediatamente, sem perguntas.

O app Podcasts que faz o download do episódio mais recente de um podcast imediatamente após se inscrever.
Depois de se inscrever em um podcast, o download do episódio mais recente é feito imediatamente.

Baixar um episódio de podcast é uma operação que possivelmente pode demorar mais. A API Background Fetch permite delegar os downloads ao navegador, que os cuida em segundo plano. No Android, o navegador, por sua vez, pode até delegar esses downloads para o sistema operacional, assim, o navegador não precisa estar em execução contínua. Quando o download for concluído, o service worker do seu app será ativado e você poderá decidir o que fazer com a resposta.

Como compartilhar e interagir com outros aplicativos

O app Podcasts se integra naturalmente a outros aplicativos. Por exemplo, quando clico com o botão direito em um episódio que eu gosto, ele pode ser compartilhado com outros apps no meu dispositivo, como o app Mensagens. Ele também se integra naturalmente à área de transferência do sistema. Posso clicar com o botão direito do mouse em qualquer episódio e copiar um link.

O menu de contexto do app Podcasts invocado em um episódio com a opção "Compartilhar episódio → Mensagens" selecionada.
Compartilhar um episódio de podcast com o app Mensagens.

As APIs Web Share e Web Share Target permitem que seu app compartilhe e receba mensagens de texto, arquivos e links de e para outros aplicativos no dispositivo. Embora ainda não seja possível para um aplicativo da web adicionar itens de menu ao menu de clique com o botão direito integrado do sistema operacional, existem muitas outras maneiras de criar links para e de outros aplicativos no dispositivo. Com a API Async Clipboard, você pode ler e gravar programaticamente dados de texto e imagem (imagens PNG) na área de transferência do sistema. No Android, você pode usar a API Contact Picker para selecionar entradas no gerenciador de contatos do dispositivo. Se você oferece um app específico da plataforma e um PWA, é possível usar a API Get InstallRelated Apps para verificar se o app específico da plataforma está instalado. Nesse caso, não é necessário incentivar o usuário a instalar o PWA ou aceitar notificações push da Web.

Atualização de app em segundo plano

Nas configurações do app Podcasts, posso configurar o app para fazer o download automático de novos episódios. Assim, eu nem preciso pensar sobre isso, o conteúdo atualizado sempre estará lá. Mágica.

No menu de configurações do app Podcasts na seção "Geral", em que a opção "Atualizar Podcasts" está definida como "A cada hora".
Podcasts configurados para verificar novos episódios a cada hora.

A API Periodic Background Sync permite que o app atualize o conteúdo regularmente em segundo plano sem precisar que ele esteja em execução. Isso significa que o novo conteúdo está disponível de forma proativa para que seus usuários possam começar a analisá-lo imediatamente sempre que quiserem.

Estado sincronizado na nuvem

Ao mesmo tempo, minhas assinaturas são sincronizadas em todos os dispositivos que pertencem a mim. Como sempre, não preciso me preocupar em manter minhas inscrições de podcast sincronizadas. Da mesma forma, não preciso ter medo que a memória do meu dispositivo móvel seja consumida por episódios que já ouvi no computador. O estado de reprodução é mantido em sincronia, e os episódios ouvidos são excluídos automaticamente.

No menu de configurações do app Podcasts na seção "Avançado", em que a opção "Sincronizar assinaturas entre dispositivos" está ativada.
O estado é sincronizado na nuvem.

A sincronização de dados de estado do app é uma tarefa que pode ser delegada à API Background Sync. A operação de sincronização em si não precisa acontecer imediatamente, apenas às vezes, e talvez até quando o usuário já tiver fechado o app de novo.

Controles da tecla de mídia de hardware

Quando estou ocupado com outro aplicativo (por exemplo, lendo uma página de notícias no navegador Chrome), ainda posso controlar o app Podcasts com as teclas de mídia do meu laptop. Não é necessário mudar para o aplicativo apenas para avançar ou voltar.

Teclado mágico do Apple MacBook Pro com teclas de mídia com anotações.
As chaves de mídia permitem controlar o app Podcasts (Fonte).

As chaves de mídia são compatíveis com a API Media Session. Assim, os usuários podem usar as teclas de mídia de hardware em teclados físicos, fones de ouvido ou até mesmo controlar o app da Web usando as teclas de mídia de software dos smartwatches. Outra ideia para suavizar as operações de busca é enviar um padrão de vibração quando o usuário procura uma parte significativa do conteúdo, por exemplo, passando os créditos de abertura ou um limite de capítulo.

Multitarefas e atalho de apps

E, claro, posso executar várias tarefas ao mesmo tempo no app Podcasts em qualquer lugar. O app tem um ícone claramente distinguível que eu também posso colocar no meu computador ou dock de aplicativos para que o Podcasts seja iniciado imediatamente quando eu quiser.

O seletor de tarefas do macOS com vários ícones de apps para você escolher, um deles é o app Podcasts.
Multitarefas de volta para o app Podcasts.

Os Progressive Web Apps podem ser instalados em computadores e dispositivos móveis na tela inicial, no menu "Iniciar" ou na base de aplicativos. A instalação pode acontecer com base em uma solicitação proativa ou totalmente controlada pelo desenvolvedor do app. O artigo O que é necessário para instalar? aborda tudo o que você precisa saber. Quando você executa várias tarefas, os PWAs parecem independentes do navegador.

Ações rápidas no menu de contexto

As ações mais comuns do app, Pesquisar novos conteúdos e Procurar novos episódios, estão disponíveis no menu de contexto do app na Dock. No menu Opções, também posso abrir o app no momento do login.

Menu de contexto do ícone do app Podcasts mostrando as opções "Pesquisar" e "Procurar novos episódios".
As ações rápidas estão disponíveis imediatamente no ícone do app.

Ao especificar atalhos de ícones do app no manifesto do app da Web do PWA, é possível registrar rotas rápidas para tarefas comuns que os usuários podem acessar diretamente do ícone do app. Em sistemas operacionais como o macOS, os usuários também podem clicar com o botão direito do mouse no ícone do app e configurar a inicialização dele no momento do login. Estamos trabalhando em uma proposta para executar no login.

Atuar como app padrão

Outros apps iOS e até sites ou e-mails podem ser integrados ao app Podcasts usando o esquema de URL podcasts://. Se eu seguir um link como podcasts://podcasts.apple.com/podcast/the-css-podcast/id1042283903 enquanto estiver usando o navegador, vou acessar o app Podcasts e posso decidir se inscrever ou ouvir o podcast.

O navegador Chrome mostrando uma caixa de diálogo de confirmação perguntando ao usuário se ele quer abrir o app Podcasts.
É possível abrir o app Podcasts diretamente no navegador.

Ainda não é possível processar esquemas de URL totalmente personalizados, mas uma proposta de manuseio de protocolo de URL para PWAs está em desenvolvimento. No momento, a melhor alternativa é registerProtocolHandler() com um prefixo de esquema web+.

Integração com o sistema de arquivos local

Talvez você não pense nisso imediatamente, mas o app Podcasts se integra naturalmente ao sistema de arquivos local. Quando faço o download de um episódio de podcast, ele fica armazenado no ~/Library/Group Containers/243LU875E5.groups.com.apple.podcasts/Library/Cache no meu laptop. Ao contrário, digamos que ~/Documents, esse diretório não foi feito para ser acessado diretamente por usuários normais, mas está lá. Além dos arquivos, outros mecanismos de armazenamento são mencionados na seção Conteúdo off-line.

O Finder do macOS navegou para o diretório do sistema do app Podcasts.
Os episódios de podcast são armazenados em uma pasta especial do app do sistema.

A API File System Access permite que os desenvolvedores tenham acesso ao sistema de arquivos local do dispositivo. Você pode usá-la diretamente ou por meio da Biblioteca de Suporte browser-fs-access, que fornece um substituto para navegadores que não são compatíveis com a API, de maneira transparente. Por motivos de segurança, os diretórios do sistema não são acessíveis na Web.

Aparência da plataforma

Há uma coisa mais sutil que é evidente para um aplicativo iOS, como Podcasts: nenhum dos rótulos de texto é selecionável e todo o texto se mistura com a fonte do sistema da máquina. Além disso, minha escolha do tema de cores do sistema (modo escuro) é respeitada.

O app Podcasts no modo escuro.
O app Podcasts é compatível com os modos claro e escuro.
O app Podcasts no modo claro.
O app usa a fonte padrão do sistema.

Ao utilizar a propriedade CSS user-select com o valor de none, você pode impedir que elementos da IU sejam selecionados acidentalmente. No entanto, não use essa propriedade de forma abusiva para tornar o conteúdo do app não selecionável. Ele só pode ser usado para elementos da interface, como textos de botões etc. O valor system-ui para a propriedade CSS font-family permite especificar a fonte da interface padrão do sistema a ser usada para seu app. Por fim, seu app pode obedecer à preferência do esquema de cores do usuário, respeitando a escolha de prefers-color-scheme, com um controle de modo escuro opcional para substituí-la. Outra decisão é o que o navegador deve fazer ao alcançar o limite de uma área de rolagem, por exemplo, para implementar a função pull para atualizar personalizada. Isso é possível com a propriedade CSS overscroll-behavior.

Barra de título personalizada

Ao observar a janela do app Podcasts, você nota que ele não tem uma barra de título e uma barra de ferramentas clássicas integradas, como a janela do navegador Safari, por exemplo, mas uma experiência personalizada que parece uma barra lateral encaixada na janela do player principal.

A barra de bloco e a barra de ferramentas integradas do navegador Safari.
Barra de título personalizada para divisão do app Podcasts.
Barras de título personalizadas do Safari e do Podcasts.

Isso não é possível no momento, mas estamos trabalhando na personalização da barra de título. No entanto, você pode (e precisa) especificar as propriedades display e theme-color do manifesto do app da Web para determinar a aparência da janela do aplicativo e decidir quais controles padrão do navegador (possivelmente nenhum deles) serão exibidos.

Animações rápidas

As animações no aplicativo são animadas e suaves nos Podcasts. Por exemplo, quando abro a gaveta Episode Notes à direita, ela desliza elegantemente para dentro. Quando removo um episódio dos meus downloads, os episódios restantes flutuam e consomem o espaço da tela que foi liberado pelo episódio excluído.

O app Podcasts com a gaveta "Episode Notes" aberta.
Animações no app, como a abertura de uma gaveta, são dinâmicas.

Animações de alta performance na Web certamente são possíveis se você considerar várias práticas recomendadas descritas no artigo Animações e desempenho. As animações de rolagem, como costumam ser vistas em conteúdos paginados ou em carrosséis de mídia, podem ser aprimoradas com o recurso Snap de rolagem do CSS. Para ter controle total, use a API Web Animations.

Conteúdo exibido fora do app

O app Podcasts no iOS pode exibir conteúdo em outros locais além do aplicativo real, por exemplo, na visualização de widgets do sistema ou na forma de uma sugestão da Siri. Ter calls-to-action proativas e baseadas no uso que exigem apenas um toque para interagir pode aumentar muito a taxa de reengajamento de um app como os Podcasts.

Visualização de widget do iOS mostrando o app Podcasts sugerindo um novo episódio de um podcast.
O conteúdo do app é exibido fora do app Podcasts principal.

A API Content Index permite que seu aplicativo informe ao navegador qual conteúdo do PWA está disponível off-line. Isso permite que o navegador exiba esse conteúdo fora do app principal. Ao marcar o conteúdo interessante no app como adequado para reprodução de áudio speakable e usar a marcação estruturada em geral, é possível ajudar os mecanismos de pesquisa e assistentes virtuais, como o Google Assistente, a apresentar suas ofertas em uma perspectiva ideal.

Widget de controle de mídia na tela de bloqueio

Quando um episódio está sendo reproduzido, o app Podcasts mostra um belo widget de controle na tela de bloqueio com metadados, como a arte, o título e o nome do podcast.

Widget de reprodução de mídia do iOS na tela de bloqueio mostrando um episódio de podcast com metadados avançados.
A mídia aberta no app pode ser controlada na tela de bloqueio.

A API Media Session permite especificar metadados, como artes, títulos de faixas etc., que são exibidos na tela de bloqueio, em smartwatches ou em outros widgets de mídia no navegador.

Notificações push

As notificações push se tornaram um incômodo na Web, embora as solicitações de notificação estejam muito mais silenciosas agora. Mas, se usados corretamente, podem agregar muito valor. Por exemplo, o app Podcasts para iOS pode me notificar sobre novos episódios de podcasts em que me inscrevi ou recomendar novos, bem como me alertar sobre novos recursos do app.

App iOS Podcasts na tela de configurações "Notificações" mostrando o botão de notificação "Novos episódios" ativado.
Os apps podem enviar notificações push para informar o usuário sobre novos conteúdos.

A API Push permite que seu app receba notificações push para que você possa avisar os usuários sobre eventos importantes relacionados ao PWA. Para notificações que precisam ser disparadas em um momento conhecido no futuro e que não exigem uma conexão de rede, use a API Notification Triggers.

Selos de ícone do app

Sempre que há novos episódios disponíveis para um dos podcasts em que me inscrevi, um selo de ícone de app no ícone da tela inicial do Podcasts é exibido, mais uma vez me incentivando a interagir novamente com o app de uma maneira que não seja invasiva.

Tela de configurações do iOS mostrando o botão "Bônus" ativado.
Os selos são uma forma sutil dos aplicativos informarem os usuários sobre novos conteúdos.

É possível definir selos de ícones do app com a API Badging. Isso é especialmente útil quando o PWA tem alguma noção de itens "não lidos" ou quando você precisa de um meio para chamar a atenção do usuário para o app de forma discreta.

A reprodução de mídia tem prioridade em relação às configurações de economia de energia

Durante a reprodução de podcasts, a tela pode ser desligada, mas o sistema não entrará no modo de espera. Os apps também podem manter a tela ativada, por exemplo, para mostrar letras de músicas ou legendas.

Preferências do macOS na seção "Economia de energia".
Os apps podem manter a tela ativada.

A API Screen Wake Lock permite impedir que a tela seja desligada. A reprodução de mídia na Web impede automaticamente que o sistema entre no modo de espera.

Descoberta de apps em uma app store

Embora o app Podcasts faça parte da experiência para computadores macOS, no iOS ele precisa ser instalado pela App Store. Uma pesquisa rápida por podcast, podcasts ou apple podcasts imediatamente abre o app na App Store.

A pesquisa por "podcasts" na App Store do iOS mostra o app Podcasts.
Os usuários aprenderam a descobrir apps em app stores.

Embora a Apple não permita PWAs na App Store, no Android, você pode enviar seu PWA em uma Atividade confiável na Web. O script bubblewrap facilita essa operação. Esse script também é o que capacita internamente o recurso de exportação de apps para Android do PWABuilder, que pode ser usado sem tocar na linha de comando.

Resumo de recursos

A tabela abaixo mostra uma visão geral compacta de todos os recursos e fornece uma lista de recursos úteis para realizá-los na Web.

Engenharia de Recursos úteis para fazer isso na Web
Pode funcionar off-line.
Conteúdo off-line disponível e mídia reproduzível
Download proativo em segundo plano
Como compartilhar e interagir com outros aplicativos
Atualização de apps em segundo plano
Estado sincronizado na nuvem
Controles de teclas de mídia de hardware
Multitarefas e atalho de apps
Ações rápidas no menu de contexto
Atuar como app padrão
Integração do sistema de arquivos local
Aparência da plataforma
Barra de título personalizada
Animações rápidas
Conteúdo exibido fora do app
Widget de controle de mídia na tela de bloqueio
Notificações push
Selos de ícone do app
A reprodução de mídia supera as configurações de economia de energia
Descoberta de apps em uma app store

Conclusão

Os PWAs evoluíram muito desde seu lançamento em 2015. No contexto do Projeto Fugu 🐡, a equipe do Chromium, de várias empresas, está trabalhando para solucionar as últimas lacunas. Ao seguir apenas alguns dos conselhos deste artigo, é possível se aproximar um pouco desse sentimento de app e fazer com que os usuários esqueçam que estão lidando com "apenas um site", porque a maioria deles não se importa como seu app é criado (e por que deveria?), contanto que pareça um app real.

Agradecimentos

Este artigo foi revisado por Kayce Basques, Joe Medley, Joshua Bell, Dion Almaer, Ade Oshineye, Pete LePage, Sam Thoroo, Reilly Grante Grantsand.