JavaScript – uma linha do tempo

Juntei acontecimentos que eu julguei interessantes para o crescimento da linguagem e botei em uma linha do tempo que vocês podem conferir abaixo, ou em tela cheia aqui! Dá pra ter uma idéia de como chegamos onde chegamos, e pra onde estamos indo. Cliquem nas setas nas laterais pra passar slide por slide ou cliquem e arrastem na linha do tempo ali em baixo pra navegar pra onde quiserem. Como sempre, os links são 90% da diversão do negócio. Vale observar atentamente acontecimentos que levaram um ao outro. A declaração do Facebook dizendo que HTML5 é lento, a Sencha implementando uma versão HTML5 do app do Facebook rodando rapidíssimo, e logo em seguida, o Facebook lança React. Ou a popularização do ajax depois do lançamento do gmail, por exemplo. Ou o surgimento de javascript isomórfico na mesma época que havia uma preocupação com reaproveitar código entre browsers (definição de ES5) e entre dispositivos (PhoneGap), e logo após nodejs ser lançado. Estou trabalhando em um jeito de deixar essas informações open-source pra quem quiser colaborar, editar, etc, mas ainda não está pronto! No meio tempo, me mandem um comment que eu edito!

Contribuições:
Thomas Paula
Rafael Gomes Dantas

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.