Frameworks front-end: soluções ou problemas inchados?

Publicados: 2022-03-11

Estruturas de front-end modernas exigem que você baixe um ambiente de desenvolvimento completo com dependências e compile seu código antes mesmo de tentar visualizá-lo em seu navegador. Isto é uma coisa boa? O problema é que estamos construindo sites mais complexos ou os frameworks são complexos por si só, introduzindo um nível desnecessário de complexidade?

O desenvolvimento da Web hoje evoluiu muito desde os anos 90; somos capazes de criar experiências inteiras que estão muito próximas do que qualquer aplicativo nativo pode fazer, e o processo de desenvolvimento também mudou. Já se foram os dias em que ser um desenvolvedor web front-end era uma questão de abrir o Bloco de Notas, digitar algumas linhas de código, verificá-lo no navegador e carregá-lo em uma pasta FTP.

O desenvolvimento web front-end do passado

Devo começar afirmando o óbvio: o mundo não é como era há 10 anos. (Chocante, eu sei.) A única coisa que permanece constante é a mudança. Antigamente, tínhamos muito poucos navegadores, mas havia muitos problemas de compatibilidade. Hoje, você não vê coisas como “melhor visualizado no Chrome 43.4.1”, mas naquela época era bastante comum. Temos mais navegadores agora, mas menos problemas de compatibilidade. Por quê? Por causa do jQuery . jQuery satisfez a necessidade de ter uma biblioteca padrão e comum que permitisse escrever código JavaScript que manipulasse o DOM sem precisar se preocupar com como ele seria executado em cada navegador e em cada versão de cada navegador - um verdadeiro pesadelo nos anos 2000 .

Os navegadores modernos podem manipular o DOM como padrão, portanto, a necessidade de tal biblioteca diminuiu bastante nos últimos anos. jQuery não é mais necessário , mas ainda podemos encontrar vários plugins extremamente úteis que dependem dele. Em outras palavras, os frameworks da Web podem não ser necessários, mas ainda são úteis o suficiente para serem populares e amplamente utilizados. Essa é uma característica comum à maioria dos frameworks da Web populares, desde React, Angular, Vue e Ember até modelos de estilo e formatação como o Bootstrap.

Por que as pessoas usam frameworks

No desenvolvimento web como na vida, ter uma solução rápida é sempre útil. Você já fez um roteador antes em JavaScript? Por que passar pelo doloroso processo de aprendizado quando você pode npm-install uma estrutura de front-end para superar o problema? O tempo é um luxo quando o cliente quer que as coisas sejam feitas ontem ou você herda o código de outro desenvolvedor projetado para um determinado framework, ou se você está integrando com uma equipe que já usa um determinado framework. Convenhamos, os frameworks existem por um motivo. Se não houvesse benefícios para eles, ninguém os estaria usando.

Então, quais são alguns dos benefícios e propriedades exclusivas de usar um framework de desenvolvimento web?

Tempo é dinheiro. Quando você está desenvolvendo um projeto e o cliente não se importa com qual framework você usa - na verdade, provavelmente nem sabe o que você usa - eles só se preocupam em obter resultados, e quanto mais rápido melhor. Frameworks estabelecidos permitem que você crie uma sensação instantânea de progresso desde o início, que o cliente deseja desde o primeiro dia. Além disso, quanto mais rápido você desenvolve, mais dinheiro você ganha, pois o tempo liberado pelo framework pode ser redirecionado para assumir mais projetos.

É tudo sobre a comunidade. Ao escolher uma estrutura, este é um ponto muito importante – quem irá ajudá-lo quando você ficar preso em um problema? Você e eu sabemos que isso vai acontecer em algum momento. Você chegará a um ponto em que precisa fazer algo que a estrutura não pretendia fazer ou que a estrutura nunca foi projetada para fornecer acesso, portanto, é essencial ter uma comunidade que o apoie. O desenvolvimento - especialmente freelance - pode ser difícil, pois você está imerso em um mundo virtual e, se você é o único desenvolvedor web front-end em uma equipe, significa que você é o único com experiência e conhecimento para encontrar um solução. Mas se a estrutura de front-end que você usa tiver um suporte sólido, haverá alguém do outro lado do mundo que enfrentou o mesmo problema e poderá ajudá-lo.

Os padrões são lindos. Você já notou que, quando você olha para um pedaço antigo de seu próprio código, pode navegar por ele com bastante facilidade? Ou pelo menos, mais facilmente do que um pedaço de código escrito por outra pessoa? Você pensa de uma certa maneira e tem sua própria maneira de nomear as coisas e organizar o código. Isso é um padrão. Todos nós os seguimos, mesmo que sejam apenas para nós mesmos. Costumamos comer coisas semelhantes no café da manhã, acordar em uma determinada hora e colocar nossas chaves no mesmo lugar todos os dias. E, de fato, se mudássemos nossas rotinas todos os dias, a vida seria muito mais difícil apenas pela sobrecarga de descobrir como fazer as coisas. Já perdeu suas chaves porque as colocou em um lugar diferente do normal? Padrões tornam a vida mais fácil. Ao trabalhar como parte de uma equipe ou comunidade de desenvolvedores, eles se tornam absolutamente indispensáveis.

Os frameworks fornecem um padrão desde o momento em que você os instala, orientando você a pensar e codificar de uma maneira específica. Você não precisa perder tempo criando um padrão com sua equipe; você pode apenas seguir como as coisas são feitas no framework. Isso facilita o trabalho em conjunto. É mais fácil procurar uma função quando você sabe que a função deve estar em um determinado arquivo, pois ela foi criada para adicionar uma rota em um SPA e, em sua estrutura, todas as rotas são colocadas em um arquivo com esse nome. Pessoas com diferentes níveis de habilidade podem trabalhar juntas se você tiver esse nível de padronização, porque enquanto os codificadores avançados sabem por que as coisas são feitas dessa maneira, mesmo os desenvolvedores juniores podem seguir o próprio padrão.

Quando os frameworks falham

Alguns anos atrás, dizer algo como “Eu não uso frameworks – não vejo nenhum benefício real deles” traria pessoas com tochas e forcados à sua porta. Mas hoje, mais e mais pessoas estão se perguntando: “Por que eu deveria usar um framework? Eu realmente preciso deles? É tão difícil codificar sem eles?”

Eu certamente sou um deles – nunca fui fã de nenhum framework específico e tenho programado sem eles por toda a minha carreira. Se eu tiver uma escolha no assunto, minha escolha é sempre: “Não, obrigado”. Venho desenvolvendo em JavaScript há anos e em ActionScript antes disso. Eu estava codificando em Flash quando a maioria das pessoas já o considerava morto. (Eu sei, eu sei... mas eu estava fazendo muitas animações, e animação em HTML simples é difícil.) Então, se você é um dos muitos que nunca pensa em codificar sem frameworks, deixe-me mostrar algumas razões pelas quais você pode estar lutando.

“Um tamanho serve para todos” é uma mentira. Você poderia imaginar escrever um único software que pode fazer tudo o que você realizou em sua carreira? Esse é um dos principais problemas com frameworks de desenvolvimento web. Seu projeto tem necessidades muito específicas, que tendemos a resolver adicionando bibliotecas, plugins ou complementos para estender o escopo do framework. Nenhuma estrutura oferece 100% do que você precisa, e nenhuma estrutura é 100% composta de coisas que você achará úteis.

Ter muito código que você não usa pode resultar em atraso no carregamento do seu site, o que se torna mais importante com cada usuário adicional. Outra questão é que a mentalidade “tamanho único” resulta em código ineficiente. Veja, por exemplo, $('sku-product').html('SKU 909090'); , que é um código jQuery que, no final, todos sabemos que será traduzido em algo como document.getElementById('sku-product').innerHTML = 'SKU 909090'; .

Esse tipo de diferença em uma única linha pode parecer sem importância, mas mudar o conteúdo de um elemento específico da página é justamente a virtude do React. Agora, o React passa pelo processo de criar uma representação do DOM e analisar as diferenças no que você tenta renderizar. Não seria mais fácil segmentar apenas o conteúdo que você deseja alterar desde o início?

Esse emaranhado de ervas daninhas por onde você está andando está crescendo espinhos. Você já esteve na situação em que está usando seu framework e tentando adicionar uma biblioteca a ele, apenas para perceber que a versão da biblioteca que você precisa não funciona bem com a versão do framework que você está usando? Às vezes, é preciso mais esforço para fazer dois pedaços de código funcionarem juntos do que apenas escrever o código você mesmo. E como os frameworks e bibliotecas que você usa geralmente são construídos em outros frameworks e bibliotecas que podem ter incompatibilidades ocultas que você nem pode prever, o problema pode se tornar exponencialmente mais complexo, chegando a um ponto em que é impossível gerenciar se você quer que o projeto continue crescendo.

Acompanhar os Joneses é uma coisa. Já trabalhou em um projeto no AngularJS apenas para descobrir que precisa de algo que não apareceu até o lançamento do Angular 4? Você sabia que o Angular 5 foi lançado? Este é outro grande problema; mesmo se você estiver aderindo a uma única estrutura de front-end, quando uma nova versão principal acontece, as coisas podem mudar tanto que o código que você trabalhou tanto para fazer nem será executado na nova versão. Isso pode resultar em qualquer coisa, desde pequenas alterações irritantes que precisam ser feitas em muitos arquivos até uma reescrita completa do seu código.

Manter-se atualizado com as compilações mais recentes de uma estrutura é um desafio, mas, na mesma nota, outras estruturas sofrem quando as atualizações param completamente e não conseguem acompanhar o restante da tecnologia. Em 2010, AngularJS e Backbone foram lançados pela primeira vez. Hoje, o Angular está em sua quinta versão principal e o Backbone está completamente fora dos holofotes. Sete anos parece muito tempo. Se você cria sites, eles provavelmente mudaram completamente em estética e função. Se você está criando um aplicativo, apostar na estrutura errada pode colocar a empresa em uma situação difícil – e cara – mais tarde, quando as coisas precisam ser reescritas.

Quando tudo que você tem é um martelo, tudo parece um prego. Se você usou frameworks de desenvolvimento web com frequência, isso provavelmente já aconteceu com você, onde uma única base de código define a forma do código que você usará no futuro, mesmo que seja relacionado apenas perifericamente. Digamos que você vai construir uma plataforma como o YouTube e quer usar o Framework X. Pode haver um ponto em que, mesmo que pareça ridículo hoje em dia, você decida usar o Flash para os vídeos porque é isso que vem construído com a estrutura.

As estruturas têm opiniões e são fortes; React, por exemplo, força você a usar JSX de uma forma específica. Você pode ver o código sendo usado dessa maneira em todos os lugares. Existe uma alternativa? sim. Mas quem usa? Isso nem sempre é uma coisa ruim, mas se você precisar executar animações complexas, talvez precise apenas de uma estrutura para animação e não de todo o React. Já vi pessoas fazerem coisas malucas como adicionar jQuery a uma página apenas para anexar um nó a um elemento, algo que poderia ser feito em vanilla JS com document.getElementById('id_of_node').appendChild(node); .

Eval é mau, mas .innerHTML é maquiavélico

Quero dedicar um tempo para explorar esse ponto separadamente porque acho que essa é uma das razões pelas quais mais pessoas não codificam sem frameworks. Quando você vê como a maioria dos códigos funciona ao tentar adicionar algo ao DOM, você encontrará um monte de HTML injetado pela propriedade .innerHTML . Todos nós parecemos concordar que eval é ruim para rodar código JavaScript, mas eu quero colocar .innerHTML no centro das atenções aqui. Ao injetar o código HTML como uma string simples, você perde qualquer referência que possa ter tido a qualquer um dos nós que criou. É verdade que você pode recuperá-los usando getElementsByClassName ou atribuindo a eles um id , mas isso não é nada prático. Ao tentar alterar o valor de um dos nós, você se verá renderizando todo o HTML novamente.

Isso é bom quando você começa a codificar. Você pode fazer muitas coisas simples facilmente sem muita experiência. O problema acontece com a complexidade dos sites modernos, que tendem a ser mais parecidos com aplicativos - isso significa que precisamos alterar constantemente os valores de nossos nós, o que é uma operação de alto custo se você estiver fazendo isso reconectando toda a estrutura via .innerHTML . O React resolve esse problema de forma eficiente por meio de um shadow DOM, e o Angular o aborda usando a vinculação como uma maneira fácil de modificar um valor mostrado em uma página. No entanto, também pode ser resolvido com bastante facilidade, acompanhando os nós que você cria e salvando os que serão reutilizados ou atualizados em variáveis. Há também outras razões para ficar longe de .innerHTML em geral.

Os maiores mitos sobre codificação sem frameworks

Tempo é dinheiro. Sim, estou trazendo esse conceito de volta de antes. Muitas pessoas acham que, se pararem de usar um framework web popular, iremos instantaneamente regredir para a internet dos anos 90, quando <marquee> era a tag favorita de todos, GIFs giratórios em um site Geocities eram modernos e ousados, Alta Vista era o go- para pesquisas na web, e contadores de visitas eram onipresentes.

Com os frameworks da Web, suas primeiras linhas de código parecem fazer muito progresso para economizar tempo, mas em algum momento, os ganhos se transformam em perdas. Você gasta seu tempo lendo sobre como fazer o framework fazer coisas para as quais ele não foi construído, como integrar bibliotecas e fazê-las funcionar bem com o framework, e descobrindo que o código que você construiu seguindo os padrões do framework não vai funcionar e agora você precisa reescrevê-lo. Quando você faz coisas sem uma estrutura, você começa mais devagar, mas faz um progresso constante. No final, é tudo sobre onde você quer que a parte fácil esteja. Não fará muita diferença no tempo total.

Meu código será maior que a Grande Muralha. Escrever sem uma estrutura é como comprar um filme em vez de assinar um serviço de streaming. Você não tem acesso instantâneo a centenas de filmes que deseja assistir, mas também não precisa gastar dinheiro em milhares de outros filmes que nunca consideraria baixar da loja. Você pode apenas escrever o que você precisa.

O intermediário é útil? Certo. Mas geralmente não é necessário . Cada linha de código que você escreve tem mais significado, pois não há necessidade de se adaptar aos requisitos de um framework. Pode parecer que você está escrevendo mais código com JavaScript puro porque a maneira de criar os elementos DOM leva linhas para criar um elemento, anexá-lo ao DOM e talvez adicionar uma classe para estilo, em vez de chamar uma única linha de código em JSX. Mas se você comparar o código usando uma biblioteca como jQuery ou React, o vanilla JS pode ser bastante semelhante em tamanho. Às vezes é mais longo, mas às vezes é mais curto também.

Não há necessidade de reinventar a roda. O mantra dos professores de ciência da computação em todos os lugares. E é verdade—simplesmente não precisa significar frameworks especificamente. Enviar uma solicitação Ajax para carregar ou salvar dados é um requisito em quase todos os aplicativos da Web, por exemplo, mas não ter uma estrutura não significa que você precisa escrever o código novamente todas as vezes. Você pode criar sua própria biblioteca ou base de código ou extrair código de outras pessoas. Quanto menor, mais fácil é modificar ou ajustar conforme necessário, por isso é útil quando você precisa de algo específico para um projeto. É mais fácil modificar 100-200 linhas de código do que navegar pela montanha de arquivos que uma biblioteca ou estrutura de terceiros pode conter.

Ele só funcionará para pequenos projetos. Este é um mito muito comum, mas não é verdade; atualmente, estou trabalhando em um sistema inteiro para gerenciar todos os aspectos de uma empresa online em um único lugar, incluindo um módulo que é algo como o Google Drive. Seja com frameworks ou sem eles, passo por etapas muito semelhantes e encontro problemas muito semelhantes. A diferença é insignificante. No entanto, sem frameworks, todo o meu código é menor e mais facilmente gerenciável.

QUERO A PROVA

OK. Vamos parar de falar sobre teoria e pular para um exemplo do mundo real. Alguns dias atrás, precisei mostrar uma lista de marcas com logomarcas para uma loja. O código inicial usava jQuery, mas apresentava um problema onde, ao carregar no Mozilla, mostrava um ícone de imagem quebrado para marcas que ainda não tinham logotipos carregados. Não podemos deixar a loja inacabada só porque a Empresa X ainda não terminou o trabalho, mas o recurso precisava ser lançado.

O código a seguir usa o equivalente jQuery de .innerHTML :

 var list_brand_names = ['amazon', 'apple', 'nokia']; var img_out = ''; for (i=0;i<list_brand_names.length;i++) { var brandName = list_brand_names[i].toLowerCase(); img_out += "<a href='/pages/" + brandName + "'><img src='images/" + brandName + "' /></a>"; } jQuery("#brand-images").html(img_out);

Sem se aprofundar muito nos prós e contras do jQuery, o problema aqui é que não temos nenhuma referência às imagens que criamos. Embora existam soluções que não envolvam alteração de código, vamos aproveitar esta oportunidade para ver como isso pode ser feito sem nenhuma biblioteca:

 var brands = ['amazon', 'apple', 'nokia']; var brand_images = document.getElementById("brand-images"); for (var iBrand = 0; iBrand < brands.length; iBrand++) { var link = document.createElement('a'); link.setAttribute('href', '/pages/' + brands[iBrand]); link.style.display = 'none'; brand_images.appendChild(link); var image = new Image(); image.src = "images/" + brands[iBrand] + "png"; image.onload = function(){ this.parentNode.style.display = ''; } link.appendChild(image); }

O código original do jQuery tinha seis linhas de comprimento, enquanto a solução vanilla JS levava doze. Para resolver o problema, ocultar cada imagem até que ela seja carregada, leva o dobro do tempo para codificar. Então vamos ver a alternativa. Pode ser resolvido em jQuery também? Confira:

 img_out += "<a href='/pages/" + brandName + "'><img src='images/" + brandName + "' onload="showImage(this)"/></a>"; function showImage(image){ image.parentNode.style.display = ""; }

Com algumas linhas adicionais de código, agora há apenas uma diferença de três linhas entre o jQuery e o vanilla, mas no jQuery, você pode ver que a linha img_out está se tornando muito complexa rapidamente, a ponto de você precisar pausar e pense cuidadosamente sobre o que você está fazendo. Codificar o DOM diretamente usando funções de nó para adicionar atributos, funções e similares pode ser mais longo, mas cada linha tem um significado mais claro e preciso, facilitando a leitura e manutenção no futuro.

Vamos dar uma olhada no React:

 function BrandLink(props) { var url = "images/" + props.brand + ".png"; return (<a href="{props.brand}"><img src={url}/></a>); } class Brands extends React.Component { constructor() { super(); this.state = {brands: ['amazon', 'apple', 'nokia']}; } render() { const links = this.state.brands.map((step, move) => { return (<BrandLink brand={step} key={step}/>); }); return (<div className="brands">{links}</div>); } } ReactDOM.render(<Brands />, document.getElementById("root"));

Esta versão é claramente sub-ótima. O código não é menor do que no vanilla, e ainda nem chegamos ao ponto de resolver o problema e ocultar os links até que a imagem dentro deles seja carregada.

Para cada exemplo, os resultados serão diferentes. Às vezes, o jQuery será mais curto. Às vezes, React vai ganhar. Há momentos em que o vanilla JS pode ser mais curto que os dois. De qualquer forma, o objetivo aqui não era provar que um era inerentemente superior ao outro, mas demonstrar que não há uma diferença significativa entre usar o vanilla JS e usar um framework quando se trata de comprimento de código.

Conclusão

Tal como acontece com praticamente qualquer problema da vida real, nada é preto ou branco. Codificar sem frameworks de desenvolvimento web pode ser a melhor solução para alguns de seus projetos e um pesadelo para outros. Assim como acontece com todas as ferramentas, a chave está em aprender não apenas como usá-las, mas quando e quais podem ser as vantagens e desvantagens de usá-las. Codificar em JavaScript puro é como em qualquer framework – dominá-lo leva tempo antes que você se sinta confortável em usá-lo.

Mas a principal diferença, pelo menos para mim, é que os frameworks vêm e vão, e mesmo que um framework seja popular por muito tempo, ele pode mudar drasticamente de uma versão para outra. JavaScript puro será uma opção por muito mais tempo, até que deixe de ser totalmente relevante e alguma outra linguagem surja. Mesmo assim, haverá mais conceitos e estratégias que você pode migrar diretamente de uma linguagem para outra do que com uma determinada estrutura para outra. Sendo o tempo e o esforço aproximadamente equivalentes no que diz respeito a um único projeto, a redução na depreciação do conhecimento e as lições que você pode levar com você para o próximo desafio são fatores muito importantes a serem considerados.

Relacionado: Os pontos fortes e os benefícios dos micro frontends