Waterfall
October 1961
Lithograph
38.0x30.0cm

React.js e como javascript escreve certo por linhas tortas

Do que se trata?

React.js é um framework em javascript escrito pelo Facebook para a construção de UIs, que recentemente tomou o mundo de assalto. Ele facilita a vida dos desenvolvedores, arrumando problemas que são reclamações constantes de quem trabalha com javascript. Mas será que não estamos frameworkizando um negócio que deveria ser solucionado de outra forma?

O tom messiânico no qual React é referido impressiona:

Facebook just taught us all how to build websites – Gyroscope Innovations

São afirmações pesadas. O design do framework é impressionante, mas vamos dissecar o que ele faz para resolver alguns dos problemas que ele se propõe a atacar.

Que problemas React resolve?

Virtual dom

O React usa um esquema onde ele acumula todas as modificações que deveriam ser feitas no DOM em uma árvore em memória, e depois que todos as consequências do código que está sendo executado atualmente (eventos, callbacks, etc) terminarem – ou seja, quando o event loop for liberado – aí sim ele vai lá e faz todas as mudanças de uma vez só. Tem uma explicação muito boa de como isso acontece por baixo dos panos aqui, pra quem tiver interesse.

O ponto é: o DOM não é lento. Para o trabalho que ele se propõe a fazer, ele é surpreendentemente rápido, só que a maioria das pessoas não entende o que ele faz. Dizer que o DOM é lento é tão estúpido quanto dizer “operações de IO são lentas”. Lentas em relação ao quê? Manipulação de valores em memória? A diferença é que elas fazem muito mais coisas do que manipulação de valores em memória. O problema do DOM é que modificá-lo programaticamente é muito fácil, então as pessoas tendem a fazer isso com uma frequência muito maior que a recomendada.

Em geral, se a pessoa está encostando no DOM o mínimo possível e ele continua lento, é por causa de um dos seguintes motivos:

  1. Seu CSS é uma bela bosta. Sério, é muito fácil fazer regras que sobrescrevem umas as outras e geram milhares de reflows.
  2. Você está fazendo coisa demais em javascript. O número de vezes que eu já vi controles que já estão implementados em HTML (checkboxes, radiobuttons, etc) programados em javascript… não dá pra contar.
  3. Você tem coisa demais na sua árvore. É o típico caso em que o cara vai lá e cria 2 divs dentro de uma div “porque não tinha outro jeito de alinhar as coisas do jeito que ele queria”. Apenas pare.

Acumular as modificações que deveriam ser feitas no DOM até o final do event loop é, de fato, uma boa prática. O que o React faz é tornar isso transparente para o desenvolvedor. React faz com que acumular mudanças no DOM para realizá-las todas de uma vez seja mais fácil do que modificar o DOM diretamente. Ele arruma um problema de design. Não de performance.

Aí eu me pergunto, pela primeira vez nesse post: e se isso fosse arrumado em uma camada mais baixa? E se o browser nos oferecesse mecanismos para um controle mais fino dos eventos de reflow/repaint provenientes de operações sobre o DOM? Será que estamos tratando isso no nível correto?

Componentes

Cara, imagina que beleza: tu vai lá no teu HTML e poe assim:

E aí PÁ teu browser substitui isso tudo por uma estrutura toda em HTML que descreve uma lista de tarefas, inclui um CSS que mostra isso bonitinho, e importa os javascripts necessários pra fazer a lista funcionar.

Isso são web components. É uma spec em desenvolvimento, um padrão aberto. E tem vários frameworks por aí que atacam esse problema. Polymer, Angular, Ember, etc. Os problemas? Isso gera uma cacetada de imports que vão virar mais requests, mais volume de dados, a compatibilidade dos browsers pra lidar com isso não está exatamente estável, etc.

React propõe um design onde o HTML para renderizar um componente possa ser colocado dentro do arquivo javascript que conhece ele:

Essa é a parte que me deixa empolgado. Os caras lá do Facebook nos mostram o seguinte: Separar HTML de javascript não é separação de responsabilidades. É separação de tecnologia. Estamos usando as duas coisas para gerenciar views. Se a gente se dispor a abraçar o capeta, a gente tem menos imports, menos acoplamento (só quem conhece o HTML de um componente é ele mesmo) e de quebra sai da herança maldita do Rails onde os componentes eram destripados entre 3 pastas diferentes.

A implementação disso por debaixo dos panos ainda não é 100%, o suporte dos browsers em relação a isso continua complicado, e ainda usamos gambiarras pra poder escrever um código um pouco melhor. React arruma um problema de arquitetura aqui. Não de implementação.

O ponto é: se há um padrão aberto disponível, será que não estamos resolvendo isso no nível errado? Será que não deveríamos tornar tarefa dos browsers a resolução de web components de acordo com o padrão sendo desenvolvido? Será que no futuro isso não vai ser desnecessário?

Adaptadores de código nativo

O pessoal do Facebook anunciou nessa semana o React Native para iOS e Android. É possível abstrair componentes nativos (sliders, botões, eventos de toque, etc) em código javascript usando React, e fazer o mesmo código (ou quase o mesmo) funcionar em seu aparelho favorito.

Tenho opiniões divididas sobre esse tópico:

Em relação a ter código que pode ser usado em plataformas diferentes, a motivação disso é clara, e já não estamos na primeira geração de tentativas de resolver esse problema. Flash, Java, .NET, PhoneGap, Titanium… Como contraponto de adaptar componentes nativos para serem usados em JS, temos o que o FirefoxOS está fazendo, de expor APIs com controle de autorização para serem usadas no browser. Se isso fosse um padrão, o que mudaria na nossa forma de desenvolver?

Voltando um pouco ao ponto de componentes: se Web Components estivesse mais estável, poderíamos ter componentes que tem o mesmo aspecto visual de componentes nativos do iOS ou Android, e várias aplicações poderiam compartilhar o mesmo código, a mesma rede de distribuição desses scripts (CDN), o mesmo cache, etc. Será que haveria necessidade de termos essa camada de adaptação JS <-> Nativo?

Será que estamos resolvendo isso na camada certa?

Como JS progride

A parte mais interessante desta pergunta é que resolver as coisas na camada errada em javascript em geral não é um problema: é um arauto de mudança.

Depois da popularização em massa de jQuery com seus seletores, document.querySelector e document.querySelectorAll foram adotados em larga escala nos browsers e hoje são um padrão.

É bacana encarar essas formas de arrumar problemas de design e arquitetura do ecossistema onde desenvolvemos aplicações para a web como uma forma de sugerir melhorias que eventualmente sejam transferidas ao nível mais eficiente. Já aconteceu antes. Acontecerá de novo.

O React se posicionar como um framework faz todo o sentido do mundo para o Facebook, que já tem uma aplicação que é o caso de uso perfeito (coincidência? o que será que veio primeiro? a aplicação ou o framework? haha :P). É necessário olhar friamente as features que React nos oferece e ver o que faz sentido dentro da nossa aplicação. Sempre é possível fazer mais com menos.

A arquitetura e o design do React são de fato uma obra de arte, e ele merece essa admiração. Mas o fato das funcionalidades virem embutidas como um framework é limitante em relação às formas que as pessoas podem adotar as técnicas que React propõe em suas aplicações.

4 opiniões sobre “React.js e como javascript escreve certo por linhas tortas”

  1. Ótimo post! Parabéns!! Faz tempo que só uso ExtJS e me deixou até curioso de ver como ele funciona por baixo. Acredito que ele faça algo parecido com o React, pois tem uma séria de recursos para controlar o rendering dos componentes dele.

    Muito interessante mesmo!

  2. Fantástico! Gostei muito da dinâmica com que o post foi escrito, com uma linguagem de fácil compreensão e ao mesmo tempo, focado nos detalhes mais interessantes, parabéns pelo excelente trabalho! Ansioso pelos próximos! Um grande abraço!

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *