A plataforma Web percorreu um logo caminho desde que o HTML5 se tornou popular e as pessoas começaram a olhar o JavaScript como uma linguagem que pode construir aplicações complexas. Muitas APIs surgiram e existe conteúdo abundante sobre como os navegadores podem tratar todas elas.
Esta série especifica de artigos irá um passo além e se concentra em como essas tecnologias podem ser usadas na prática, não somente para construir demonstrações ou protótipos, mas como os profissionais tem usado elas em produção. Nessa série de artigos pós HTML5, vamos além do modismo e mostraremos detalhes práticos dos especialistas sobre o que realmente funcionou com eles. Também abordaremos tecnologias (como AngularJS) que vão um passo além e definem o futuro de como os padrões e desenvolvimento web irão evoluir.
Esse artigo do InfoQ é parte da serie "Próxima geração do HTML5 e JavaScript". Você pode assinar para receber notificações via RSS.
Em agosto de 2014, o Codecademy decidiu adotar as bibliotecas do Facebook para escrever as interfaces de usuários em JavaScript, o React.js, como parte de um inspeção do nosso ambiente de aprendizado. Inicialmente, corremos para corrigir os problemas procurando exemplos de como o React pode ser usado em aplicações complexas, sendo que a maioria dos tutoriais focam em exemplos específicos de demonstrações indo em caminho oposto as discussões mais gerais sobre problemas específicos em grandes aplicações. Esse artigo foca em ambos, uma visão geral do React e algumas dicas sobre considerações específicas do uso do React em grandes aplicações web.
O que é React?
Resumindo: o React é uma biblioteca para construir interfaces de usuários com JavaScript. Ao invés da abordagem tradicional de escrever interfaces de usuários (UI), o React trata cada elemento de UI como uma máquina de estados. O React não é um "framework" como no caso do AngularJS. Embora o Facebook algumas vezes descreva o React como o "V do MVC", acredito que essa descrição não é útil, já que as aplicações não precisam utilizar o modelo MVC. O React ajuda a construir rápidas interfaces de usuários que podem tratar interações complexas sem poluir o código.
Após começar a trabalhar com o React podemos ficar menos preocupados com essas funcionalidades:
- O React trata o DOM.
A manipulação do DOM é custosa. O React veio amplamente como uma forma de resolver esse problema. O React minimiza a quantidade de manipulação do DOM mantendo seu próprio DOM virtual e somente renderizando quando necessário, um feito que permite uma implementação diferente de alto desempenho.
Isso significa que raramente manipularemos o DOM diretamente; ao invés, deixe o React tratar a manipulação do DOM. Essa funcionalidade é a base para muito do design do React. Se sentir que está abusando da API do React ou tentando mudar a sua forma de fazer isso, há muita chance de estar interferindo na forma como o React entende o DOM.
Essa funcionalidade também permite construir a renderização no lado servidor usando o Node.js, que permite facilmente servir páginas que são amigáveis para ao SEO (Search Engine Optimization).
- O React pensa declarativamente em componentes.
No React, tudo precisa ser subclasse da classe Component. Os componentes tem propriedades (determinados pelos seus pais) e estado (que podem mudar eles próprios, no entanto baseados nas ações dos usuários). Os componentes podem renderizar e se comportar com base somente em seus estados e propriedades; os componentes são máquinas de estados. Esse modelo encoraja a construção de UIs modulares e na prática facilitam o trabalho e a razão da UI.
- O React casa com as marcações do JavaScript.
Embora possa ser meio estranho escrever HTML no JavaScript, no React essa é a forma natural de fazer as coisas. Usar o JSX -- puro JS misturado com marcações HTML -- é opcional, mas altamente recomendado. O React argumenta que como as marcações são fracamente acopladas com o JavaScript que os controla, eles podem viver bem no mesmo arquivo.
- As informações fluem em uma direção.
Isso é mais um padrão geral do React do que uma regra restritiva. O fluxo de informações tende a ser unidirecional no React. Revisaremos esse padrão posteriormente assim que consideremos como o fluxo de informação necessita ser tratado em grandes aplicações.
Anatomia de uma aplicação React
Para tornar esses princípios mais concretos, vamos olhar como o React trabalha no ambiente de aprendizado do Codecademy.
(Clique na imagem para ampliar)
Figura 1: O ambiente de aprendizado.
Como podemos ver no screenshot o ambiente de aprendizado principal consiste de muitos elementos de UI diferentes. Alguns elementos como: o cabeçalho, menu e navegação estão presentes todo tempo. No entanto, dependendo do exercício, alguns componentes aparecem e desaparecem -- o navegador web, a linha de comando e o editor de código podem ser misturados e apresentados dependendo da lição.
A solução lógica é criar os componentes React para várias partes. No screenshot a seguir está destacado os principais componentes React:
(Clique na imagem para ampliar)
Figura 2: O ambiente de aprendizado e componentes relacionados.
Cada componente pode também conter diversos componentes filhos; por exemplo, o painel de lição da esquerda é atualmente composto por vários componentes:
(Clique na figura para ampliar)
Figura 3: Os sub componentes que compõe o componente de Lição.
Nesse caso, deixamos o React determinar o que apresentar no painel de lição. Por exemplo:
- Somente mostrar a botão "Report a Problem" se o usuário estiver autenticado;
- Somente renderiza a "Instructions section" se o exercício tiver testes.
Além disso, o React trata o fluxo de informações entre esse e outros componentes. Há um componente pai para todo o ambiente de aprendizado, que continua tratando o estado tal como os exercícios do usuário. Esse componente pai dita como seus filhos podem ser renderizados atribuindo suas props (propriedades).
Agora, vamos verificar um exemplo de comunicação de componentes, usando os seguintes componentes nesse componente de árvore bem simplificado:
- LearningEnvironment (Ambiente de aprendizado);
- CodeEditor (Editor de código);
- ErrorDisplayer (Apresentar erros);
- RunButton (Botão de execução);
- Navigation (Navegação).
(Clique na figura para ampliar)
Figura 4: Alguns componentes envolvidos no código de submissão.
Como tratamos o fluxo de trabalho de um usuário tentando executar seus códigos? Queremos executar os testes sobre os códigos e apresentar uma mensagem de erro ou permitir sua continuação. Aqui está um possível fluxo:
- Quando o usuário clica no botão Run, ele informa seu pai, o CodeEditor, da ação via callback;
- O CodeEditor, então informa ao seu pai, o Learning Environment, lançando outro callback, passando através do código atual do usuário;
- O Learning Environment executa os testes no código do usuário.
Com base no resultado:
- O LearningEnvironment define a propriedade errorMessage no CodeEditor, que então define a propriedade errorMessage no seu filho, o ErrorDisplayers;
- Se o usuário passar em todos os testes do exercício, o LearningEnvironment define a propriedade de progresso no componente Navigation.
As atualizações da UI podem ser executadas com uma simples chamada de função. Se os componentes forem declarados como esse método de renderização do LearningEnvironment (novamente, uma versão simplificada):
render: function() { return( <div> <CodeEditor error={this.state.error} /> <Navigation mayProceed={this.state.mayProceed} /> </div>); }
Lembre-se, o React mistura JavaScript com marcações HTML. Nesse caso, o método render está definindo um LearningEnvironment como algo que contém ambos componentes CodeEditor e Navigation.
Podemos atualizar o estado do LearningEnvironment, que acionará uma renderização e atualiza os componentes filhos se necessário:
handleTestResult: function(currentIndex, passing, error) { this.setState({ error: error, mayProceed: passing // currentIndex === this.state.currentExercise.tests.length-1 }); }
É isso, o React trata as atualizações do UI de forma simples e elegante.
Considerações para grandes aplicações
Fluxo da informação
Como notado previamente, o React não utiliza necessariamente o modelo MVC; de fato, estamos livres para tratar o fluxo de informações, mas precisamos de uma estratégia consistente para obter informações. E se não quiser passar para baixo o encadeamento das propriedades dos componentes que não precisam atualmente dele, apenas para alcançar um componente filho do filho do filho, etc? Se aquele nó folha aceitar entradas do usuário, como alertar o componente filho do filho do filho dessa mudança?
Em grandes aplicações, isso pode ser frustrante. Mesmo em um exemplo simples como o anterior, como o botão Run comunica a ação do usuário com o LearningEnvironment? Precisamos passar sempre chamadas de callback, mas é difícil escrever componentes realmente modulares e reusáveis dessa maneira.
A solução do Codecademy vem sendo gerar adaptadores para comunicação que gerenciam o fluxo de informações entre componentes específicos. Ao invés de passar as chamadas de callbacks, os componentes de alto nível, como o CodeEditor também recebem um Adapter, que fornece uma interface única para importantes tarefas de comunicação. Por exemplo, quando o CodeEditor está presente, o LearningEnvironment gerenciará um Adapter que pode emitir e processar os eventos relacionados a submissão de códigos.
O conceito principal tirado disso é que independentemente de como é tratado o fluxo da informações entre a árvore de componentes, a equipe deve entrar em acordo sobre uma estratégia coerente.
Integração
O React é fácil de usar, mas precisa de algumas ferramentas para aproveitá-lo efetivamente no seu workflow. Por exemplo, usamos:
- Um script que observa mudanças locais em arquivos .jsx e recompila eles se necessário;
- Um servidor separado de node.js que trata a renderização no lado do servidor;
- As ferramentas do desenvolvedor para auto geração de novos arquivos de componentes conforme a necessidade.
Nenhuma delas são muito complicadas. Gulp é uma ótima escolha para observar os .jsx, mas escrevemos a nossa própria. Para geração de novos arquivos de componentes usamos um simples script bash, que também segue nossa convenção de nomes. Se estamos usando um servidor node.js para renderizar no lado servidor, tenha cuidado; pode ser difícil forçar que o require.js pegue as mudanças no seu código React, então temos nossos observadores que reiniciam o servidor node conforme a necessidade.
Porque o React?
Quando estavamos revisando o ambiente de aprendizado, tínhamos que determinar quais ferramentas ou frameworks usar; eventualmente escolhemos o React e estamos muito felizes com a escolha. (Mais detalhes sobre como escolhemos um framework Javascript, ou não, estão nessa apresentação: https://www.youtube.com/watch?v=U5yjPG5mHZ8)
Aqui estão alguns aspectos que gostamos no React:
É testado para a batalha.
O React é usado em produção pelo Facebook e Instagram, então podemos confiar no seu desempenho e confiabilidade. Até agora, ele está servindo muito bem e não temos experimentado qualquer problema significante.
Os componentes são fáceis de entender.
Porque o React trata somente com componentes individuais, que renderizam com base em seu estado interno, é fácil de conceituar o que deve acontecer a qualquer momento. Sua aplicação torna-se efetivamente uma grande máquina de estados. Isso significa que podemos testar partes individuais da UI de forma isolada, bem como adicionar novos componentes sem se preocupar com interferências no restante da aplicação.
É fácil para o SEO.
Como o React foi construído para suportar a renderização no lado servidor, podemos servir páginas praticamente completas para mecanismos de buscas, que é um grande impulso para o SEO com muito pouco esforço necessário. Sabendo que somente funciona no Node; já que a aplicação principal do Codecademy é escrita em Rails executando um servidor Node separado que apenas trata a renderização do React.
O React é compatível com código legado e flexível o bastante para o futuro.
Enquanto que a adoção de um framework inteiro é um grande compromisso, é possível experimentar calmamente a adição do React com o código base já existente. Do mesmo modo, se for necessário podemos remover o React no futuro com bastante facilidade. No Codecademy, decidimos escrever um novo projeto inteiro no React, para testar e aprender quais as melhores formas de aproveitá-lo; isso funcionou muito bem e agora usamos para todos os novos elementos de UI. Recomendamos mergulhar e construir alguns experimentos e então considerar como o React pode ser integrado em seu código já existente.
Para de se preocupar com código repetitivo.
Menos tempo escrevendo códigos repetitivos significa mais tempo resolvendo problemas interessantes. Dessa perspectiva, o React é conciso e leve. Aqui está o código mínimo necessário para criar um novo componente:
var dummyComponent = React.createClass({ render: function() { return (<div>Marcações HTML no JS, que legal!</div>); } });
Curto e direto ao ponto. O que não há para gostar?
Temos uma comunidade para construí-lo.
O React é uma comunidade que está crescendo rapidamente. Quando encontramos problemas, há muitas pessoas para discutir. E porque muitas empresas grandes estão usando o React em produção (Facebook, Instagram, Yahoo!, Github e Netflix, são alguns nomes), estamos em uma boa empresa.
Resumindo
O React é uma biblioteca leve, poderosa e testada para construir interfaces de usuários com JavaScript. Ele não é um framework completo, e sim uma poderosa ferramenta que pode mudar a maneira como abordamos o desenvolvimento front-end. Descobrimos que ele pode ser uma ferramenta incrivelmente útil para o desenvolvimento front-end e foi uma escolha muito boa. Trabalhar com o React teve um impacto dramático na maneira de como pensar nas interfaces de usuários. Também é bom ver o React crescendo: agora que o Facebook está trazendo o React para o mobile com o React Native.
Se quiser começar a usar o React, o tutorial é o lugar mais lógico para se começar. Há também diversos posts abordando os conceitos principais do React (como nesses slides). Siga adiante e tente construir algo, descubra sua opinião a respeito da abordagem do React no desenvolvimento front-end.
Sobre a autora
Bonnie Eisenman é uma engenheira de software da Codeacademy.com. Uma graduada recente de Ciências da Computação em Princeton, ela também tem um pouco de conhecimento em hardware, adora trabalhar com Arduinos e programação musical em seu tempo livre. Encontre a como @brindelle no Twitter.
A plataforma Web percorreu um logo caminho desde que o HTML5 se tornou popular e as pessoas começaram a olhar o JavaScript como linguagem que pode construir aplicações complexas. Muitas APIs surgiram e existe conteúdo abundante sobre como os navegadores podem tratar todas elas.
Esta série específica de artigos irá um passo além e se concentra em como essas tecnologias podem ser usadas na prática, não somente para construir demonstrações ou protótipos, mas como os profissionais tem usado elas em produção. Nessa série de artigos pós HTML5, vamos além do modismo e mostraremos detalhes práticos dos especialistas sobre o que realmente funcionou com eles. Também abordaremos tecnologias (como AngularJS) que vão um passo além e definem o futuro de como os padrões e desenvolvimento web irão evoluir.
Esse artigo do InfoQ é parte da serie "Próxima geração do HTML5 e JavaScript". Você pode assinar para receber notificações via RSS.