Projetando e construindo um aplicativo da Web progressivo sem uma estrutura (Parte 1)
Publicados: 2022-03-10Como um aplicativo da web realmente funciona? Não quero dizer do ponto de vista do usuário final. Digo no sentido técnico. Como um aplicativo da Web realmente é executado? O que dá o pontapé inicial? Sem qualquer código clichê, qual é a maneira correta de estruturar um aplicativo? Particularmente um aplicativo do lado do cliente em que toda a lógica é executada no dispositivo do usuário final. Como os dados são gerenciados e manipulados? Como você faz a interface reagir às mudanças nos dados?
Esses são os tipos de perguntas que são simples de contornar ou ignorar completamente com uma estrutura. Os desenvolvedores buscam algo como React, Vue, Ember ou Angular, siga a documentação para começar a trabalhar e ir embora. Esses problemas são tratados pela caixa de truques do framework.
Isso pode ser exatamente como você quer as coisas. Indiscutivelmente, é a coisa inteligente a fazer se você quiser construir algo com um padrão profissional. No entanto, com a magia abstraída, você nunca aprende como os truques são realmente realizados.
Você não quer saber como os truques são feitos?
Eu fiz. Então, decidi tentar construir um aplicativo básico do lado do cliente, sem estrutura, para entender esses problemas por mim mesmo.
Mas, estou me adiantando um pouco; um pouco de fundo primeiro.
Antes de iniciar esta jornada eu me considerava altamente proficiente em HTML e CSS, mas não em JavaScript. Como eu senti que tinha resolvido as maiores dúvidas que eu tinha sobre CSS para minha satisfação, o próximo desafio que me propus foi entender uma linguagem de programação.
O fato era que eu era relativamente iniciante com JavaScript. E, além de hackear o PHP do Wordpress, também não tive exposição ou treinamento em nenhuma outra linguagem de programação.
Deixe-me qualificar essa afirmação de 'nível iniciante'. Claro, eu poderia ter interatividade trabalhando em uma página. Alternar classes, criar nós DOM, anexá-los e movê-los, etc. Mas quando chegou a hora de organizar o código para qualquer coisa além disso, eu não tinha noção. Eu não estava confiante em construir nada que se aproximasse de um aplicativo. Eu não tinha ideia de como definir um conjunto de dados no JavaScipt, muito menos manipulá-lo com funções.
Eu não entendia os 'padrões de design' do JavaScript — abordagens estabelecidas para resolver problemas de código frequentemente encontrados. Eu certamente não tinha noção de como abordar decisões fundamentais de design de aplicativos.
Você já jogou 'Top Trumps'? Bem, na edição de desenvolvedor web, meu cartão seria algo assim (marcas de 100):
- CSS: 95
- Copie e cole: 90
- Linha do cabelo: 4
- HTML: 90
- JavaSript: 13
Além de querer me desafiar em nível técnico, também me faltavam habilidades de design.
Com quase exclusivamente codificação de designs de outras pessoas na última década, minhas habilidades de design visual não tiveram nenhum desafio real desde o final dos anos 2000. Refletindo sobre esse fato e minhas insignificantes habilidades em JavaScript, cultivei um crescente senso de inadequação profissional. Era hora de resolver minhas deficiências.
Um desafio pessoal tomou forma em minha mente: projetar e construir uma aplicação web JavaScript do lado do cliente.
Sobre Aprendizagem
Nunca houve recursos tão bons para aprender linguagens de computação. Particularmente JavaScript. No entanto, demorei um pouco para encontrar recursos que explicassem as coisas de uma maneira que clicasse. Para mim, 'You Don't Know JS' de Kyle Simpson e 'Eloquent JavaScript' de Marijn Haverbeke foram uma grande ajuda.
Se você está começando a aprender JavaScript, certamente precisará encontrar seus próprios gurus; pessoas cujo método de explicação funciona para você.
A primeira coisa importante que aprendi foi que é inútil tentar aprender com um professor/recurso que não explica as coisas de uma maneira que você entenda. Algumas pessoas olham para exemplos de funções com foo
e bar
e grok instantaneamente o significado. Eu não sou uma dessas pessoas. Se você também não é, não assuma que linguagens de programação não são para você. Apenas tente um recurso diferente e continue tentando aplicar as habilidades que você está aprendendo.
Também não é certo que você irá desfrutar de qualquer tipo de momento eureka onde tudo de repente 'clique'; como o equivalente de codificação de amor à primeira vista. É mais provável que seja preciso muita perseverança e aplicação considerável de seus aprendizados para se sentir confiante.
Assim que você se sentir um pouco competente, tentar aplicar seu aprendizado lhe ensinará ainda mais.
Aqui estão alguns recursos que achei úteis ao longo do caminho:
- Fun Fun Fun Canal do YouTube
- Cursos de Visão Plural de Kyle Simpson
- JavaScript30.com de Wes Bos
- JavaScript Eloquente por Marijn Haverbeke
Certo, isso é praticamente tudo que você precisa saber sobre por que cheguei a este ponto. O elefante agora na sala é, por que não usar uma estrutura?
Por que não reagir, Ember, Angular, Vue Et Al
Embora a resposta tenha sido mencionada no início, acho que o assunto de por que uma estrutura não foi usada precisa ser expandido.
Há uma abundância de estruturas JavaScript de alta qualidade e bem suportadas. Cada um projetado especificamente para a construção de aplicativos da Web do lado do cliente. Exatamente o tipo de coisa que eu queria construir. Eu te perdôo por se perguntar o óbvio: tipo, err, por que não usar um?
Aqui está a minha posição sobre isso. Quando você aprende a usar uma abstração, é basicamente isso que você está aprendendo — a abstração. Eu queria aprender a coisa, não a abstração da coisa.
Lembro-me de aprender um pouco de jQuery no passado. Embora a adorável API me permita tornar as manipulações do DOM mais fáceis do que nunca, fiquei impotente sem ela. Eu não conseguia nem alternar classes em um elemento sem precisar de jQuery. Encarregue-me de alguma interatividade básica em uma página sem jQuery para me apoiar e eu tropecei no meu editor como um Samson tosquiado.
Mais recentemente, enquanto tentava melhorar minha compreensão de JavaScript, tentei entender um pouco sobre Vue e React. Mas, no final das contas, nunca tive certeza de onde o JavaScript padrão terminava e começava o React ou o Vue. Minha opinião é que essas abstrações valem muito mais a pena quando você entende o que elas estão fazendo por você.
Portanto, se eu fosse aprender algo, eu queria entender as partes principais da linguagem. Dessa forma, eu tinha algumas habilidades transferíveis. Eu queria manter algo quando o sabor atual da estrutura do mês foi deixado de lado para a próxima 'coisa nova'.
OK. Agora, estamos atualizados sobre por que esse aplicativo foi feito e também, gostando ou não, como ele seria feito.
Vamos passar para o que essa coisa ia ser.
Uma ideia de aplicação
Eu precisava de uma ideia de aplicativo. Nada muito ambicioso; Eu não tinha nenhuma ilusão de criar uma empresa iniciante ou aparecer no Dragon's Den - aprender JavaScript e noções básicas de aplicativos era meu objetivo principal.
O aplicativo precisava ser algo que eu tivesse uma chance de conseguir tecnicamente e fazer um trabalho de design meio decente para arrancar.
Tempo tangente.
Fora do trabalho, organizo e jogo futebol de salão sempre que posso. Como organizador, é difícil notar mentalmente quem me enviou uma mensagem para dizer que está jogando e quem não. Normalmente são necessárias 10 pessoas para um jogo, 8 de cada vez. Há uma lista de cerca de 20 pessoas que podem ou não ser capazes de jogar cada jogo.
A ideia do aplicativo que eu escolhi era algo que permitia escolher jogadores de uma lista, dando-me uma contagem de quantos jogadores confirmaram que podiam jogar.
Ao pensar mais sobre isso, senti que poderia ampliar um pouco mais o escopo para que pudesse ser usado para organizar qualquer atividade simples baseada em equipe.
É certo que eu mal tinha sonhado com o Google Earth. No entanto, ele tinha todos os desafios essenciais: design, gerenciamento de dados, interatividade, armazenamento de dados, organização de código.
Em termos de design, eu não me preocuparia com nada além de uma versão que pudesse rodar e funcionar bem em uma viewport de telefone. Eu limitaria os desafios de design para resolver os problemas apenas em telas pequenas.
A ideia central certamente se inclinou para aplicativos de estilo 'to-do', dos quais havia muitos exemplos existentes para se inspirar, além de ter diferença suficiente para fornecer alguns desafios exclusivos de design e codificação.
Recursos pretendidos
Uma lista inicial de recursos que eu pretendia projetar e codificar era assim:
- Uma caixa de entrada para adicionar pessoas à lista;
- A capacidade de definir cada pessoa para 'in' ou 'out';
- Uma ferramenta que divide as pessoas em equipes, padronizando para 2 equipes;
- A capacidade de excluir uma pessoa da lista;
- Alguma interface para 'ferramentas'. Além de dividir, as ferramentas disponíveis devem incluir a capacidade de baixar os dados inseridos como um arquivo, fazer upload de dados salvos anteriormente e excluir todos os jogadores de uma só vez;
- O aplicativo deve mostrar uma contagem atual de quantas pessoas estão 'In';
- Se não houver pessoas selecionadas para um jogo, deve ocultar o divisor de equipe;
- Modo de pagamento. Uma alternância nas configurações que permite que os usuários 'in' tenham uma alternância adicional para mostrar se pagaram ou não.
No início, isso é o que eu considerava as características para um produto mínimo viável.

Projeto
Os desenhos começaram em pedaços de papel. Foi esclarecedor (leia-se: esmagador) descobrir quantas ideias que eram incríveis na minha cabeça se tornaram ridículas quando submetidas ao escasso escrutínio proporcionado por um desenho a lápis.
Muitas ideias foram, portanto, rapidamente descartadas, mas o outro lado era que, ao esboçar algumas ideias, invariavelmente levava a outras ideias que eu nunca teria considerado de outra forma.
Agora, os designers que estão lendo isso provavelmente ficarão tipo, “Duh, é claro”, mas isso foi uma verdadeira revelação para mim. Os desenvolvedores estão acostumados a ver projetos de estágios posteriores, raramente vendo todas as etapas abandonadas ao longo do caminho antes desse ponto.
Uma vez feliz com algo como um desenho a lápis, eu tentava recriá-lo no pacote de design, Sketch. Assim como as ideias caíram no estágio de papel e lápis, um número igual não conseguiu passar pelo próximo estágio de fidelidade do Sketch. Aqueles que pareciam se sustentar como pranchetas no Sketch foram então escolhidos como candidatos a codificar.
Eu descobriria, por sua vez, que quando esses candidatos eram código embutido, uma porcentagem também não funcionava por vários motivos. Cada etapa de fidelidade expôs novos desafios para que o projeto fosse aprovado ou reprovado. E um fracasso me levaria literal e figurativamente de volta à prancheta.
Como tal, em última análise, o design com o qual acabei é um pouco diferente do que originalmente tinha no Sketch. Aqui estão as primeiras maquetes do Sketch:


Mesmo assim, eu não tinha ilusões; era um projeto básico. No entanto, neste ponto eu tinha algo que eu estava relativamente confiante que poderia funcionar e eu estava tentando construir.
Requerimentos técnicos
Com alguns requisitos iniciais de recursos e uma direção visual básica, era hora de considerar o que deveria ser alcançado com o código.
Embora a sabedoria recebida dite que a maneira de fazer aplicativos para dispositivos iOS ou Android é com código nativo, já estabelecemos que minha intenção era construir o aplicativo com JavaScript.
Eu também estava ansioso para garantir que o aplicativo marcasse todas as caixas necessárias para se qualificar como um Progressive Web Application, ou PWA, como são mais comumente conhecidos.
Caso você não saiba o que é um Progressive Web Application, aqui está o 'elevator pitch'. Conceitualmente, imagine um aplicativo da Web padrão, mas que atenda a alguns critérios específicos. A adesão a esse conjunto de requisitos particulares significa que um dispositivo de suporte (pense em um telefone celular) concede privilégios especiais ao aplicativo da Web, tornando o aplicativo da Web maior do que a soma de suas partes.
No Android, em particular, pode ser quase impossível distinguir um PWA, construído apenas com HTML, CSS e JavaScript, de um aplicativo construído com código nativo.
Aqui está a lista de verificação do Google de requisitos para que um aplicativo seja considerado um Progressive Web Application:
- O site é servido por HTTPS;
- As páginas são responsivas em tablets e dispositivos móveis;
- Todos os URLs de aplicativos são carregados offline;
- Metadados fornecidos para Adicionar à tela inicial;
- Primeiro carregue rápido mesmo em 3G;
- Site funciona em vários navegadores;
- As transições de página não parecem ser bloqueadas na rede;
- Cada página tem um URL.
Além disso, se você realmente quer ser o bichinho do professor e ter seu aplicativo considerado um 'Exemplar Progressive Web App', ele também deve atender aos seguintes requisitos:
- O conteúdo do site é indexado pelo Google;
- Os metadados do Schema.org são fornecidos quando apropriado;
- Metadados sociais são fornecidos quando apropriado;
- URLs canônicos são fornecidos quando necessário;
- As páginas usam a API de histórico;
- O conteúdo não salta à medida que a página é carregada;
- Pressionar para trás de uma página de detalhes mantém a posição de rolagem na página de lista anterior;
- Quando tocadas, as entradas não são obscurecidas pelo teclado na tela;
- O conteúdo é facilmente compartilhável no modo autônomo ou em tela cheia;
- O site é responsivo em todos os tamanhos de tela de telefone, tablet e desktop;
- Nenhum prompt de instalação de aplicativo é usado excessivamente;
- O prompt Adicionar à tela inicial é interceptado;
- Primeiro carregue muito rápido mesmo em 3G;
- O site usa a rede de primeiro cache;
- O site informa adequadamente o usuário quando ele está offline;
- Fornecer contexto ao usuário sobre como as notificações serão usadas;
- A interface do usuário que incentiva os usuários a ativar as notificações push não deve ser excessivamente agressiva;
- O site escurece a tela quando a solicitação de permissão é exibida;
- As notificações push devem ser oportunas, precisas e relevantes;
- Fornece controles para habilitar e desabilitar notificações;
- O usuário está conectado em todos os dispositivos por meio da API de gerenciamento de credenciais;
- O usuário pode pagar facilmente por meio da interface do usuário nativa da API de solicitação de pagamento.
Caramba! Eu não sei sobre você, mas esse segundo monte de coisas parece muito trabalho para um aplicativo básico! Acontece que há muitos itens lá que não são relevantes para o que eu planejei de qualquer maneira. Apesar disso, não tenho vergonha de dizer que baixei a vista para passar apenas nos testes iniciais.
Para uma seção inteira de tipos de aplicativos, acredito que um PWA é uma solução mais aplicável do que um aplicativo nativo. Onde jogos e SaaS provavelmente fazem mais sentido em uma loja de aplicativos, utilitários menores podem viver de forma bastante feliz e com mais sucesso na Web como aplicativos Web progressivos.
Ainda sobre o assunto de me esquivar do trabalho duro, outra escolha feita no início foi tentar armazenar todos os dados para o aplicativo no próprio dispositivo do usuário. Dessa forma, não seria necessário conectar-se a serviços e servidores de dados e lidar com logins e autenticações. Para onde estavam minhas habilidades, descobrir a autenticação e armazenar os dados do usuário parecia quase certamente morder mais do que eu poderia mastigar e exagerar para o mandato do aplicativo!
Opções de tecnologia
Com uma ideia bastante clara sobre qual era o objetivo, a atenção se voltou para as ferramentas que poderiam ser empregadas para construí-lo.
Decidi desde o início usar o TypeScript, que é descrito em seu site como “… um superconjunto tipado de JavaScript que compila em JavaScript simples”. O que eu tinha visto e lido da linguagem eu gostava, especialmente o fato de ela ter aprendido tão bem a análise estática.
Análise estática significa simplesmente que um programa pode examinar seu código antes de executá-lo (por exemplo, quando está estático) e destacar problemas. Ele não pode necessariamente apontar problemas lógicos, mas pode apontar para códigos não conformes em relação a um conjunto de regras.
Qualquer coisa que pudesse apontar meus (certamente muitos) erros à medida que eu avançava tinha que ser uma coisa boa, certo?
Se você não estiver familiarizado com o TypeScript, considere o seguinte código em JavaScript vanilla:
console.log(`${count} players`); let count = 0;
Execute este código e você receberá um erro algo como:
ReferenceError: Cannot access uninitialized variable.
Para aqueles com um pouco de habilidade em JavaScript, para este exemplo básico, eles não precisam de uma ferramenta para dizer que as coisas não terminarão bem.
No entanto, se você escrever esse mesmo código no TypeScript, isso acontecerá no editor:

Estou recebendo alguns comentários sobre minha idiotice antes mesmo de executar o código! Essa é a beleza da análise estática. Esse feedback muitas vezes era como ter um desenvolvedor mais experiente sentado comigo pegando erros à medida que eu avançava.
TypeScript principalmente, como o nome indica, vamos especificar o 'tipo' esperado para cada coisa no código. Isso evita que você 'coaja' inadvertidamente um tipo para outro. Ou tentar executar um método em um dado que não é aplicável — um método de matriz em um objeto, por exemplo. Este não é o tipo de coisa que necessariamente resulta em um erro quando o código é executado, mas certamente pode introduzir bugs difíceis de rastrear. Graças ao TypeScript, você obtém feedback no editor antes mesmo de tentar executar o código.
O TypeScript certamente não era essencial nessa jornada de descoberta e eu nunca encorajaria ninguém a usar ferramentas dessa natureza a menos que houvesse um benefício claro. Configurar ferramentas e configurar ferramentas em primeiro lugar pode ser um desperdício de tempo, portanto, considere definitivamente sua aplicabilidade antes de mergulhar.
Existem outros benefícios oferecidos pelo TypeScript que abordaremos no próximo artigo desta série, mas os recursos de análise estática foram suficientes para eu querer adotar o TypeScript.
Havia considerações indiretas sobre as escolhas que eu estava fazendo. Optar por construir o aplicativo como um aplicativo da Web progressivo significava que eu precisaria entender os Service Workers até certo ponto. Usar o TypeScript significaria introduzir ferramentas de compilação de algum tipo. Como eu gerenciaria essas ferramentas? Historicamente, eu usava o NPM como gerenciador de pacotes, mas e o Yarn? Valeu a pena usar o Yarn em vez disso? Ser focado no desempenho significaria considerar algumas ferramentas de minificação ou agregação; ferramentas como o webpack estavam se tornando cada vez mais populares e precisariam ser avaliadas.
Resumo
Eu reconheci a necessidade de embarcar nessa busca. Meus poderes de JavaScript eram fracos e nada cingia os lombos tanto quanto tentar colocar a teoria em prática. Decidir construir uma aplicação web com JavaScript vanilla seria meu batismo de fogo.
Passei algum tempo pesquisando e considerando as opções para fazer o aplicativo e decidi que fazer do aplicativo um Progressive Web App fazia mais sentido para meu conjunto de habilidades e a relativa simplicidade da ideia.
Eu precisaria de ferramentas de compilação, um gerenciador de pacotes e, posteriormente, muita paciência.
Em última análise, neste ponto, a questão fundamental permaneceu: isso era algo que eu realmente poderia gerenciar? Ou seria humilhado pela minha própria inépcia?
Espero que você se junte a mim na parte dois quando puder ler sobre ferramentas de construção, padrões de design JavaScript e como fazer algo mais 'tipo aplicativo'.