Um Primeiro Olhar sobre o Gea, um Framework de UI Compiler-First
Gea é um framework de UI JavaScript compiler-first com JSX, stores em classes e patches diretos no DOM. O artigo analisa props, tamanho e maturidade.
Gea é um framework de UI JavaScript compiler-first: um plugin do Vite lê o seu JSX durante o build, descobre quais nós do DOM dependem de quais estados e emite patches diretos no DOM. Não existe virtual DOM e nada faz diff em tempo de execução.
Frameworks que prometem compilar o runtime até fazê-lo desaparecer surgem a cada poucos meses, e o post de lançamento geralmente apresenta o discurso de venda e os números, com pouca atenção aos trade-offs. As páginas do Gea seguem praticamente a mesma linha, portanto o que vem a seguir expõe o modelo tal como o projeto o descreve, indica de onde vem cada número e examina com mais rigor aquilo que realmente difere do React e do Vue: props de objeto bidirecionais.
Principais Conclusões
- O Gea conecta a reatividade em tempo de compilação: um plugin do Vite analisa o JSX, mapeia o estado para os nós do DOM e emite patches direcionados em vez de embarcar um virtual DOM.
- Todo o modelo se resume a três regras: stores são classes que estendem
Store, componentes são classes com um métodotemplate()ou funções simples, e valores computados são getters. - Uma prop de objeto ou array entrega ao filho o mesmo proxy que o pai detém, de modo que uma escrita no filho também altera o estado do pai. Primitivos, por outro lado, são copiados.
- O projeto reporta 121 B em brotli para o hello world, 4,9 kb para um todo interativo e uma pontuação de 1,02 no js-framework-benchmark, todos medidos no Gea 1.3.0 pelo mantenedor contra os builds do próprio mantenedor.
- Com um único mantenedor, um número de versão inicial e nenhuma revisão independente, o Gea vale uma tarde de experimentação em vez de uma aposta em produção.
O Que É o Gea?
O Gea move a reatividade do runtime para o build. De acordo com o site do projeto, seu plugin do Vite lê o seu JSX durante a compilação, determina quais nós do DOM dependem de quais partes do estado e conecta patches que tocam apenas esses nós. A comparação com o Vue coloca o contraste de forma direta: onde o Vue reexecuta uma função de render e faz o diff da árvore resultante, o Gea simplesmente executa as funções de patch que o compilador já gerou. Seu estado fica em classes comuns que o Gea envolve em um proxy profundo, de modo que uma atribuição ordinária como this.count++ já é suficiente para mover o DOM. Não há nada para envolver e nenhuma lista de dependências para manter sincronizada. O README apresenta essa linhagem como uma continuação das bibliotecas anteriores do mantenedor, erste.js e regie, agora com transformações de JSX em tempo de compilação.
Qual É o Modelo do Gea em Três Linhas?
Toda a superfície do Gea cabe em três regras: stores são classes que estendem Store, componentes são classes com um método template() ou funções simples, e valores computados são getters comuns. O contador do README mostra tudo isso:
// counter-store.ts
import { Store } from '@geajs/core'
class CounterStore extends Store {
count = 0
increment() { this.count++ }
decrement() { this.count-- }
}
export default new CounterStore()
// app.tsx
import { Component } from '@geajs/core'
import counterStore from './counter-store'
export default class App extends Component {
template() {
return (
<div>
<h1>{counterStore.count}</h1>
<button click={counterStore.increment}>+</button>
<button click={counterStore.decrement}>-</button>
</div>
)
}
}
A documentação de componentes explica que o plugin do Vite reescreve componentes de função como componentes de classe durante o build, e que o template de um componente é executado uma única vez. Tudo o que vem depois disso é um patch, não uma re-renderização.
Em Que o JSX do Gea Difere do React?
O JSX do Gea se parece com o do React, e uma convenção realmente precisa mudar: escreva class onde o React espera className. Os eventos são mais tolerantes. O README os escreve como atributos em minúsculas, tais como click, input e change, mas a comparação com o Vue na documentação confirma que onClick, onInput e onChange também são aceitos, de modo que handlers no estilo React funcionam como estão. E ref não recebe um objeto de ref: o Gea coloca o nó do DOM diretamente na propriedade do componente assim que a renderização termina.
// React habit // Gea equivalent
<div className="card" <div class="card"
onClick={save} /> click={save} />
O padrão de ref da documentação é um campo de classe inicializado como null, ref={this.videoEl} no elemento e, depois, uso direto de this.videoEl após a renderização.
Props: Objetos São o Proxy do Pai
O maior afastamento em relação a React e Vue é o que acontece com uma prop não primitiva. A documentação de componentes do Gea explica que o filho recebe exatamente o mesmo proxy que o pai detém, de modo que qualquer escrita feita pelo filho vai parar no estado do pai e aparece no DOM do pai. Primitivos se comportam como argumentos de função em JavaScript: o filho recebe uma cópia, e reatribuí-la não muda nada fora do filho. A documentação mostra um filho fazendo exatamente isso:
export default class Editor extends Component {
rename() {
this.props.user.name = 'Bob' // parent's DOM updates too
}
template({ user }) {
return <button click={this.rename}>{user.name}</button>
}
}
A regra se mantém por mais profunda que a árvore seja. Passe a mesma referência para um neto, deixe-o escrever no objeto, e todo ancestral que observa aquele dado é redesenhado. Nada precisa ser elevado com um callback, e não há nenhuma etapa de emit ou v-model no meio do caminho.
| Filho atualiza o pai | React | Vue | Gea |
|---|---|---|---|
| Objetos/arrays | Props de callback | emit / v-model | Mutação direta do proxy compartilhado |
| Primitivos | Props de callback | emit / v-model | Não é possível (passagem por valor) |
A documentação apresenta isso puramente como um benefício, e as questões em aberto permanecem sem resposta. Em uma árvore de 40 componentes, qual componente mutou este objeto? A convenção unidirecional do React existe em parte para que as mudanças tenham uma origem rastreável; o Gea troca isso por objetividade, e ninguém ainda documentou quanto custa esse trade-off em escala. O mesmo vale para a própria conexão em tempo de compilação: como o compilador lida com código que ele não consegue enxergar estaticamente é algo que a documentação não aborda.
Tamanho e Velocidade, Conforme o Projeto os Reporta
Todo número de performance sobre o Gea é uma medição do próprio projeto contra os builds do próprio mantenedor dos frameworks concorrentes. As tabelas de tamanho do README colocam uma aplicação hello-world em 121 B de JavaScript em brotli, ao lado dos builds do projeto para Solid (3,6 kb), Svelte (8,5 kb), Vue (20,7 kb) e React (50,8 kb), com o todo interativo em 4,9 kb. Ambos os conjuntos de números foram obtidos no Gea 1.3.0 a partir de builds de produção recém-gerados com Vite 8.0.10.
A pontuação de 1,02 no js-framework-benchmark, onde 1,00 é JavaScript vanilla escrito à mão, vem da execução da suíte pelo próprio projeto no Chrome 147, e não de uma rodada oficial publicada. A frase “framework de UI compilado mais rápido” na página inicial é uma afirmação do projeto construída sobre esses mesmos números autoexecutados, não um resultado de terceiros.
O Que Acompanha o Gea?
A tabela de pacotes do README lista @geajs/core, @geajs/vite-plugin, @geajs/ssr para renderização no servidor, create-gea para scaffolding, além de @geajs/ui (componentes headless construídos sobre o Zag.js) e @geajs/mobile para primitivos mobile. gea-tools é uma extensão para VS Code e Cursor, não um pacote npm.
A entrada mais incomum é o ferramental de IA. Executar npx skills add dashersw/gea instala um conjunto de agent skills que ficam no repositório em .cursor/skills/gea-framework e entregam a um assistente de codificação por IA as convenções que, de outro modo, ele teria de adivinhar: como as stores funcionam, como os componentes são declarados e em que o JSX difere. Para um framework jovem sobre o qual nenhum modelo tem dados de treinamento, distribuir as convenções como skills consumíveis pelo editor é uma decisão pragmática de onboarding.
Maturidade: O Que os Números de Versão Dizem
As tabelas de comparação e de tamanho do README foram medidas no Gea 1.3.0, e o @geajs/core já publicou desde então a versão 1.4.0, segundo as notas de release do projeto. O Gea é licenciado sob MIT e é mantido por uma única pessoa, Armagan Amcalar. Todos os números de benchmark e de tamanho são autorreportados, e ainda não existe nenhuma revisão técnica independente do framework. Para uma equipe, a conclusão é direta: o modelo é coerente e pequeno o bastante para ser avaliado em uma tarde, mas um único mantenedor, um número de versão inicial e números não verificados significam que ainda não há base de evidências para apostar um produto nele.
A afirmação genuinamente interessante do Gea não é o tamanho do bundle; é a de que classes, funções e getters comuns podem sustentar um modelo completo de reatividade se um compilador fizer as conexões. A forma mais rápida de julgar essa afirmação é fazer o scaffold do contador e do exemplo de props acima e ver se a semântica bidirecional de objetos parece clareza ou um passivo de depuração no seu tipo de base de código.
Perguntas Frequentes
Como o Gea difere do Solid e do Svelte?
Os três se apoiam em um compilador, mas o primitivo reativo é diferente. O Solid constrói a reatividade sobre signals que rodam no navegador, e o Svelte 5 usa sua sintaxe de runes compilada a partir de sua própria linguagem de template. O Gea não tem nenhum dos dois: o estado é mantido em classes comuns envolvidas por um proxy profundo, e um plugin do Vite lê JSX padrão em tempo de build para conectar patches diretos no DOM.
Quais hooks de ciclo de vida os componentes do Gea possuem?
Componentes de classe do Gea expõem quatro hooks. created(props) dispara entre o construtor e a primeira renderização, e é onde a documentação coloca a lógica de inicialização. onAfterRender() é executado assim que o elemento do componente está no documento e seus filhos foram montados. onAfterRenderAsync() aguarda o próximo requestAnimationFrame. dispose() remove o componente do DOM e desmonta seus observers e filhos. A documentação recomenda componentes de classe sempre que você precisar de qualquer um desses recursos.
O Gea funciona com TypeScript?
Sim. Um componente de classe declara o formato de suas props com 'declare props', uma declaração ambiente que não emite JavaScript, mas permite que qualquer editor com suporte a TypeScript complete e verifique os atributos, sem envolver nenhum plugin do framework. Anotar o parâmetro de template() como this['props'] leva esses tipos para as variáveis desestruturadas dentro do método; se você omitir isso, elas voltam a ser any. Componentes de função recebem o mesmo tratamento por meio de uma anotação normal de parâmetro.
Como inicio um novo projeto Gea?
Faça o scaffold com 'npm create gea@latest', a ferramenta create-gea do projeto. Builds do Gea rodam sobre o Vite, e o @geajs/vite-plugin é o que cuida da transformação do JSX, da conexão da reatividade e do hot reloading. A documentação também inclui um guia de uso no navegador para rodar o Gea sem uma etapa de build, além de guias para o router, o kit de UI e os pacotes mobile.
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers.
Star on GitHub12k