Nossas primeiras 50.000 estrelas no GitHub
Há apenas três anos e meio nós abrimos o código de uma pequena biblioteca chamada React. A jornada desde aquele dia tem sido incrivelmente excitante.
Camiseta Comemorativa
Para comemorar as 50.000 estrelas no GitHub, Maggie Appleton do egghead.io desenhou para nós uma camiseta especial, que está disponível para compra no Teespring somente por uma semana até quinta feira, 06 de Outubro. Maggie também escreveu um post mostrando todos os diferentes conceitos que ela criou antes de escolher como seria o design final.
As camisetas são bem macias usando o tecido tri-blend da American Apparel’s. Nós também temos camisetas para crianças e macacões para bebês disponíveis.
- Camisetas para Adultos (corte reto e ajustadas)
- Camisetas para crianças
- Camisetas Infantis
- Onesies para bêbês
Todos os ganhos das camisetas serão doados para o CODE2040, uma organização sem fins lucrativos que cria acesso, conscientização e oportunidades em tecnologia para minorias não representadas com um foco especifico em talentos afrodescendente e latinos.
Arqueologia
Gastamos muito tempo tentando explicar conceitos que existem atrás do React e problemas que ele busca resolver, mas não falamos muito sobre como o React evoluiu antes de se tornar um projeto de código aberto. Este momento parece bom para lembrarmos os primeiros commits e compartilharmos alguns dos momentos importantes e fatos engraçados.
A história inicia com nossa organização de anúncios, onde nós estávamos construindo aplicativos web do lado do cliente incrivelmente sofisticados utilizando um framework MVC interno chamado BoltJS. Aqui está um exemplo de como era um código do framework Bolt:
var CarView = require('javelin/core').createClass({
name: 'CarView',
extend: require('container').Container,
properties: {
wheels: 4,
},
declare: function() {
return {
childViews: [
{ content: 'I have ' },
{ ref: 'wheelView' },
{ content: ' wheels' }
]
};
},
setWheels: function(wheels) {
this.findRef('wheelView').setContent(wheels);
},
getWheels: function() {
return this.findRef('wheelView').getContent();
},
});
var car = new CarView();
car.setWheels(3);
car.placeIn(document.body);
//<div>
// <div>I have </div>
// <div>3</div>
// <div> wheels</div>
//</div>
Bolt introduziu um número de APIs e recursos que acabariam eventualmente entrando no React, incluindo o método render
, createClass
, e refs
. Bolt introduziu o conceito de refs
como uma forma de criar referências para nós que podem ser utilizados imperativamente. Esta maneira foi relevante para a interoperabilidade herdada e a adoção incremental, e enquanto o React se esforçaria para ser muito mais funcional, refs
provou ser uma forma útil de sair do paradigma funcional quando surgir a necessidade.
Porém como nossas aplicações cresceram mais e ficaram mais sofisticadas, nossas base de códigos do Bolt se tornaram complicadas. Reconhecendo algumas deficiências da estrutura, Jordan Walke iniciou experimentos em um projeto paralelo chamado FaxJS. Seu objetivo foi resolver muitos dos problemas existentes no Bolt, mas de uma forma diferente. Este é o lugar onde a maioria dos fundamentos do React nasceu, incluindo props
, state
, reavaliando grandes partes da árvore para “diferenciar” a interface do usuário, a renderização do lado do servidor e conceitos básicos de componente.
TestProject.PersonDisplayer = {
structure : function() {
return Div({
classSet: { personDisplayerContainer: true },
titleDiv: Div({
classSet: { personNameTitle: true },
content: this.props.name
}),
nestedAgeDiv: Div({
content: 'Interests: ' + this.props.interests
})
});
}
};
Nasce o FBolt
Através do seu experimento FaxJS, Jordan se convence de que as APIs funcionais - que desencorajam a mutação - oferecem uma melhor, mais escalável forma de construir interfaces de usuários. Ele importou sua biblioteca na base de códigos do Facebook em Março de 2012 e renomeou a biblioteca para “FBolt”, significando uma extensão do Bolt onde os componentes são escritos em um estilo de programação funcional. Ou talvez “Fbolt” foi uma prévia do FaxJS - ele não nos contou! ;)
A interoperabilidade entre FBolt e Bolt permitiu experimentarmos a substituição de apenas um componente por vez com APIs de componentes mais funcionais. Poderíamos visitar as águas desse novo paradigma funcional, sem ter que entrar totalmente nele. Iniciamos com os componentes que estavam claramente melhor expressos funcionalmente e então continuamos depois com os demais componentes que poderíamos expressar como funções.
Percebendo que o FBolt não seria um ótimo nome para a biblioteca quando usada sozinha, Jordan Walke e Tom Occhino decidiram por um novo nome: “React.” Depois de Tom ter renomeado a biblioteca inteira, Jordan comentou:
Jordan Walke: Eu poderia acrescentar, que por uma questão de discussão, que muitos sistemas demonstram algum tipo de reatividade, mas geralmente exigem que você defina algum tipo de ouvinte (listeners) ponto a ponto e não funcionará com dados estruturados. Essa API reage a qualquer alteração de estado ou propriedade e trabalha com dados de qualquer forma (tão profundamente quanto o próprio gráfico), então acho que o nome é adequado.
A maioria dos outros commits de Tom na época estavam na primeira versão do GraphiQL, um projeto que recentemente teve seu código aberto.
Adicionando JSX
Desde 2010 o Facebook está utilizando uma extensão do PHP chamada XHP, que permite engenheiros criar interfaces de usuário utilizando XML dentro de seu código PHP. Ele foi introduzido pela primeira vez para ajudar a evitar falhas XSS, porém acabou sendo uma excelente maneira para estruturas aplicações com componentes personalizados.
final class :a:post extends :x:element {
attribute :a;
protected function render(): XHPRoot {
$anchor = <a>{$this->getChildren()}</a>;
$form = (
<form
method="post"
action={$this->:href}
target={$this->:target}
class="postLink"
>{$anchor}</form>
);
$this->transferAllAttributes($anchor);
return $form;
}
}
Antes do trabalho de Jordan ter ser entrado na base de código do Facebook, Adam Hupp implementou um conceito semelhante ao XHP para Javascript, escrito em Haskell. Este sistema permitiu que você escrevesse o seguinte dentro de um arquivo Javascript:
function :example:hello(attrib, children) {
return (
<div class="special">
<h1>Hello, World!</h1>
{children}
</div>
);
}
Isso compilaria para um código ES3 Javascript compativel:
function jsx_example_hello(attrib, children) {
return (
S.create("div", {"class": "special"}, [
S.create("h1", {}, ["Hello, World!"]),
children
]
);
}
Neste protótipo, S.create
criaria e retornaria imediatamente um nó DOM. A maioria das conversas sobre este protótipo girou em torno das características de desempenho do innerHTML
contra criar nós no DOM diretamente. Na época, seria menos ideal colocar desenvolvedores universalmente na direção da criação de nós DOM diretamente, uma vez que ele não funciona tão bem, especialmente no navegador Firefox e Internet Explorer. O CTO do Facebook, Bret Taylor entrou na discussão no momento em favor do innerHTML
ao invés do document.createElement
.
Bret Taylor: Se você não está convencido sobre o innerHTML, aqui está um pequeno comparativo. Isso não mudou no Chrome. innerHTML esta 30% mais rápido na última versão do Firefox (e muito mais do que nas versões anteriores), e 90% mais rápido no IE8.
Este projeto foi eventualmente abandonado, mas foi revivido depois que o React entrou na base de código. Jordan ignorou as discussões anteriores sobre performance introduzindo o conceito de “Virtual DOM,” embora este nome ainda não existisse.
Jordan Walke: Para a primeira etapa, eu proponho que nós façamos o mais fácil e mais genérico possível. Minha sugestão é simplesmente mapear expressões xml para funções de chamada.
<x></x>
becomesx( )
<x height=12></x>
becomesx( {height:12} )
<x> <y> </y> </x>
becomesx({ childList: [y( )] })
Neste ponto, o JSX não precisa conhecer o React - isso é apenas uma forma conveniente de escrever chamadas de função. Coincidentemente, a abstração primária do React é a função. Ok, talvez isso não seja uma coincidência ;)
Adam fez um comentário muito perspicaz, no qual agora é a forma padrão que nós escrevemos listas no React com JSX.
Adam Hupp: Eu penso que nós deveríamos tratar matrizes de elementos como um frag. Isso é muito útil para construções como:
<ul>{foo.map(function(i) { return <li>{i.data}</li>; })}</ul>
Neste caso, ul(…) irá receber um childList com um único filho, que é uma lista.
React não utilizou a implementação de Adam diretamente. Ao invés, nós criamos JSX fazendo o fork do projeto js-xml-literal, um projeto paralelo do criador do XHP, Marcel Laverdet. O JSX tomou o nome de js-xml-literal, que Jordan modificou para ser apenas um acréscimo sintático para chamadas de funções profundamente aninhadas.
API Churn
Durante o primeiro ano do React, as adoções internas estavam crescendo, mas havia muita rotatividade nas APIs dos componentes e nas convenções de nomenclatura:
project
foi renomeado paradeclare
, depois parastructure
e finalmente pararender
.Componentize
foi renomeado paracreateComponent
e finalmentecreateClass
.
Como o projeto estava prestes a se tornar aberto, Lee Byron sentou-se com Jordan Walke, Tom Occhino e Sebastian Markbåge com o objetivo de refatorar, reimplementar e renomear, um dos recursos mais amado do React - o ciclo de vida da API. Lee criou uma API bem projetada que ainda está sendo utilizada hoje em dia.
-
Conceitos
- component - Uma instância de ReactComponent
- state - Estado interno de um componente
- props - Estado externo de um componente
- markup - A string/coisas HTML que o componente gera
- DOM - O documento e elementos dentro do documento
-
Ações
- mount - Colocar um componente em um DOM
- initialize - Preparar um componente para renderização
- update - Uma transição de um estado (e propriedades) resultando em renderização
- render - Um processo sem efeitos colaterais buscando ter uma representação (markup) de um componente.
- validate - Fazer validações sobre algo criado e fornecido
- destroy - Oposto de initialize
-
Operações
- create - Fazer uma coisa nova
- get - Pegar uma coisa existente
- set - Fundir-se com a existente
- replace - Substituir
- receive - Responder a novos dados
- force - Ignorar checagens para fazer uma ação
-
Notificações
- shouldObjectAction
- objectWillAction
- objectDidAction
Em 2012, o Instagram foi adquirido pelo Facebook. Pete Hunt, quem estava trabalhando em fotos e vídeos no Facebook no momento, juntou-se a sua nova equipe web recém-formada. Ele queria construir seu website completamente em React, que estava em contraste com o modelo de adoção incremental que havia sido usado no Facebook.
Para fazer isso acontecer, o React precisou ser desacoplado da infraestrutura do Facebook, já que o Instagram não utilizava nada disso. Este projeto teve uma atuação importante para a futura decisão de abrir o código do React. Neste projeto, Pete também descobriu e promoveu um pequeno projeto chamado webpack. Ele também implementou a primitiva renderToString
, que era necessária para fazer a renderização no lado do servidor.
Quando iniciamos a nos preparar para abrir o código do React, Maykel Loomans, um designer do Instagram, fez uma simulação do que o site poderia ser. O cabeçalho acabou definindo a identidade visual do React: seu logo e a cor azul elétrica!
Em seus primeiros dias, React se beneficiou enormemente dos feedbacks, idéias e contribuições técnicas dos primeiros usuários e colaboradores em toda a empresa. Embora possa parecer um sucesso da noite para o dia, a história do React é atualmente um ótimo exemplo de como novas idéias frequentemente precisam passar por várias etapas de refinamento, interações e correções de curso, durante um longo período de tempo antes de alcançar o seu potencial máximo.
A abordagem do React para construir interfaces de usuário com princípios de programação funcional mudou a forma para nós fazemos as coisas em poucos anos. Não é preciso dizer, mas o React não seria nada sem a incrível comunidade de código aberto que é construída em torno dele!