Skip to main content

Octane: o React sem o React por baixo, e o que isso sinaliza pro ecossistema

· 8 min read
Bruno Carneiro
Fundador da @TautornTech
Octane: o React compilado, sem virtual DOM

Se você acompanha o ecossistema React de perto, provavelmente tropeçou nesse anúncio essa semana. Dominic Gannaway lançou o Octane, descrito como "o modelo de programação do React, compilado". É o sucessor declarado do Inferno, framework que o próprio Gannaway criou lá em 2016 com o mesmo pitch de performance. Um gênio indomável.

Vale parar pra entender duas coisas. Primeiro, o que ele faz tecnicamente. Segundo, e mais importante pra quem decide stack, o que a chegada dele diz sobre pra onde o React está indo.

Vamos para a maior de todas novidades da última semana!

A API que você já sabe, sem a implementação que você já conhece

Octane não pede que você aprenda um modelo mental novo. useState, useEffect, useMemo, useCallback, context, portals, Suspense, transitions. A API é a mesma, testada contra mais de 2.200 testes de conformidade retirados diretamente do facebook/react.

A diferença está inteiramente por baixo do capô:

  • Sem virtual DOM. Um compilador gera o caminho de renderização e um reconciliador com chave baseado em LIS (longest increasing subsequence), em vez de fazer diffing de uma árvore virtual em runtime.
  • Sem arrays de dependência manuais. Omita o array em useEffect, useMemo, useCallback e companhia, que o compilador infere as dependências a partir do que a closure efetivamente captura. Ele inclusive reconhece setters de estado, refs e dispatchers como estáveis.
  • Sem "rules of hooks". Hooks são associados ao call site pelo compilador, não à ordem de execução. Ou seja: podem viver dentro de um if ou depois de um return antecipado sem quebrar nada. A única regra que sobra é hook dentro de loop puro, que vira erro de compilação. O @for (operador de iteração do dialeto .tsrx) resolve isso dando a cada item seu próprio slot de estado.
  • Dois dialetos, uma linguagem. JSX/TSX padrão funciona sem alterações. O .tsrx é opcional e adiciona diretivas de controle de fluxo (@if, @for, @switch, @try) que compilam pra caminhos rápidos com chave.

Traduzindo em prático: três das dores mais chatas do React no dia a dia (memoização manual, array de dependências, ordem obrigatória dos hooks) desaparecem, e você continua escrevendo o mesmo código.

Pra ficar concreto, esse é o exemplo que o próprio README do Octane usa pra mostrar as quatro formas possíveis de useEffect:

useEffect(() => sync(room.id)); // sem array: o compilador infere [room.id] pela closure
useEffect(() => initialize(), []); // array vazio: só no mount
useEffect(() => sync(room.id), [room.id]); // deps explícitas (mantém o comportamento React)
useEffect(() => measure(), null); // null: roda depois de todo commit

Repara que a versão de cima é a que some com a dor. Você escreve o código, o compilador olha o que a closure captura e monta a lista de dependências. E se você quiser ser explícito, as três outras formas continuam valendo, com a mesma semântica do React de sempre.

O outro ponto que aparece na prática é "hook depois de early return". No React isso é erro. No Octane, funciona:

export function Panel(props) @{
const [n, setN] = useState(0);

if (props.hidden) return; // early return antes de um hook, ok

useEffect(() => {
// ...
});

<div>{n}</div>
}

Isso é possível porque o compilador amarra cada hook ao call site, não à ordem de execução. Todo mundo que já se enrolou pra evitar um if cedo em componente React entende o valor disso.


Aqui mais um exemplo do próprio Twitter (X, o nome ruim...) do miníno de como isso funciona:

De onde isso vem

Vale contextualizar quem tá por trás. Gannaway construiu o Inferno em 2016 pra testar se interfaces React-like podiam ser otimizadas de forma mais agressiva. Era um período de debate intenso sobre performance de front-end. Depois disso, ele trabalhou na equipe do próprio React, na Lexical (editor de texto do Meta) e no Svelte.

Onde ele se encaixa no mapa de frameworks compilados

O ponto mais interessante pra quem acompanha o ecossistema é que Octane não chega num vácuo. Chega num momento em que a própria fronteira "React vs. frameworks compilados" já estava se movendo.

O React Compiler já resolveu parte do problema dentro do React. Ele (antes conhecido como React Forget) chegou à versão estável e já é o padrão em frameworks como Next.js 16, fazendo memoização automática sem useMemo, useCallback ou React.memo. É a mesma dor que o Octane ataca com a inferência de dependências. A diferença é que o React Compiler ainda opera sobre um Virtual DOM. Ele elimina o trabalho manual de memoização, mas não remove a camada de reconciliação. Octane vai um passo além e tira o VDOM da equação inteiramente, como Solid e Svelte já fazem.

Solid e Svelte 5 já provaram a tese "sem VDOM". Solid usa signals com granularidade de nó de DOM, sem re-render de componente, só atualização cirúrgica do que mudou. Svelte 5 (com runes) compila pra operações de DOM diretas, com um runtime de cerca de 1,6 KB contra os ~7 KB do Solid. Pra maioria das aplicações, a diferença de performance entre essas abordagens é imperceptível. O que sugere que a proposta de valor real do Octane não é "mais rápido que Solid", e sim "a velocidade de um framework sem VDOM com a API e o ecossistema do React".

Essa é uma aposta bem específica. Em vez de pedir que devs React aprendam signals (Solid) ou runes (Svelte), Octane aposta que a API de hooks já é o vencedor de mental model, e que o que faltava era só tirar o custo de implementação dela.

tip

Traduzindo pra decisão de stack: se sua equipe já pensa em hooks, Octane te dá o ganho de performance sem custo de reciclagem de time. Se você tá começando do zero, ainda faz sentido olhar Solid/Svelte pelo modelo mental mais enxuto.

O que ainda falta para se provar

A recepção inicial teve peso real. Tanner Linsley (mantenedor do TanStack) já comentou publicamente que o TanStack está com adapters pra Octane praticamente prontos pra e outras bibliotecas da suíte. O próprio repositório já lista suporte de zustand, jotai, TanStack Query/Router/Table/Virtual, Apollo Client, Motion, StyleX, Radix, base-ui, React Hook Form, Redux/Redux Toolkit, Lexical, Recharts, visx, i18next e MDX.

Ou seja: uma tentativa de reduzir o custo de migração ao mínimo, trazendo o ecossistema React inteiro junto em vez de pedir reescrita. É isso que separa Octane de outras tentativas de "React mas mais rápido". Ele não está pedindo que o ecossistema escolha entre performance e as bibliotecas que já usa.

Parece tudo mil maravilhas mas vale a pena lembrar que esse trem está na versão ALPHA!

  • O projeto está oficialmente em alpha. A API pode mudar, e "2.200 testes de conformidade" cobre semântica de hooks, não necessariamente todos os edge cases de produção em escala.
  • A paridade dos bindings do ecossistema é variável por pacote. O próprio projeto mantém uma tabela de status (docs/bindings-status.md) admitindo que alguns portes são parciais.
  • Adotar Octane hoje significa apostar num compilador jovem pra SSR, hidratação e streaming. São áreas historicamente cheias de casos extremos difíceis de acertar de primeira.
warning

Testar em side project, spike técnico ou playground, tranquilo. Botar produto de cliente em cima de compilador alpha é receita pra dor de cabeça: quando quebrar (e vai quebrar), você vai estar debugando o compilador, não o seu código.

Dar push na main e testar em prod 🙄, o cliente avisa se deu certo ou não

Por que isso importa pro ecossistema React

O sinal mais forte que o Octane manda não é sobre o Octane em si. É sobre o consenso que se formou ao redor da API de hooks do React.

Depois de anos de "signals vs. hooks" como narrativa dominante em conferência e Twitter, temos agora três respostas distintas convergindo no mesmo diagnóstico (a implementação do React tem custo desnecessário), com prescrições diferentes:

AbordagemO que mantémO que remove
React CompilerVDOM, hooksMemoização manual
Solid / SvelteCompilação agressivaVDOM, hooks (troca por signals/runes)
OctaneHooks e API inteiraVDOM, array de deps, rules of hooks

Se Octane conseguir entregar isso com estabilidade de produção (e esse "se" ainda é grande, dado o estágio alpha), ele vira o argumento mais forte já feito de que "hooks" e "virtual DOM" nunca foram a mesma decisão de design, e que dá pra ter um sem o outro.

Isso pressiona os dois lados. O React tem que mostrar que o Compiler consegue fechar a diferença de performance sem abrir mão do VDOM. Solid e Svelte têm que justificar por que vale a pena pedir aos devs que aprendam um modelo mental novo, se a versão "compilada" do modelo antigo já resolve o problema.

Referências