12k
All articles

Un primer vistazo a Gea, un framework de UI que prioriza el compilador

Gea es un framework de UI JavaScript centrado en el compilador que usa JSX, stores en clases y parches directos del DOM. El artículo analiza props, tamaño y madurez.

OpenReplay Team
OpenReplay Team
Un primer vistazo a Gea, un framework de UI que prioriza el compilador

Gea es un framework de UI en JavaScript que prioriza el compilador: un plugin de Vite lee tu JSX durante el build, determina qué nodos del DOM dependen de qué estado y emite parches directos al DOM. No hay virtual DOM y nada hace diffing en tiempo de ejecución.

Cada pocos meses aparece algún framework que promete compilar el runtime hasta hacerlo desaparecer, y el artículo de lanzamiento suele darte el discurso y las cifras, con poco sobre las contrapartidas. Las páginas de Gea se leen prácticamente igual, así que lo que sigue expone el modelo tal y como lo describe el proyecto, señala de dónde sale cada cifra y examina con especial detenimiento aquello que sí difiere realmente de React y Vue: las props de objeto bidireccionales.

Puntos clave

  • Gea conecta la reactividad en tiempo de compilación: un plugin de Vite analiza el JSX, asocia el estado a nodos del DOM y emite parches dirigidos en lugar de enviar un virtual DOM.
  • Todo el modelo se reduce a tres reglas: los stores son clases que extienden Store, los componentes son clases con un método template() o simples funciones, y los valores computados son getters.
  • Una prop de tipo objeto o array entrega al hijo el mismo proxy que tiene el padre, de modo que una escritura en el hijo también modifica el estado del padre. Los primitivos, en cambio, se copian.
  • El proyecto reporta 121 B en brotli para un hello world, 4,9 kb para un todo interactivo y una puntuación de 1,02 en js-framework-benchmark, todo medido en Gea 1.3.0 por el mantenedor contra sus propios builds.
  • Con un único mantenedor, un número de versión temprano y sin revisión independiente, Gea merece una tarde de exploración antes que una apuesta en producción.

¿Qué es Gea?

Gea traslada la reactividad del runtime al build. Según el sitio del proyecto, su plugin de Vite lee tu JSX durante la compilación, determina qué nodos del DOM dependen de qué piezas de estado y prepara parches que solo tocan esos nodos. La comparación con Vue plantea el contraste sin rodeos: donde Vue vuelve a ejecutar una función de render y hace diffing del árbol resultante, Gea simplemente ejecuta las funciones de parcheo que el compilador ya generó. Tu estado vive en clases planas que Gea envuelve en un proxy profundo, así que una asignación corriente como this.count++ basta para mover el DOM. No hay nada que envolver ni una lista de dependencias que mantener sincronizada. El README presenta este linaje como una continuación de las librerías anteriores del mantenedor, erste.js y regie, ahora con transformaciones de JSX en tiempo de compilación.

¿Cuál es el modelo de Gea en tres líneas?

Toda la superficie de Gea cabe en tres reglas: los stores son clases que extienden Store, los componentes son clases con un método template() o simples funciones, y los valores computados son getters corrientes. El contador del README lo muestra todo:

// 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>
    )
  }
}

La documentación de componentes explica que el plugin de Vite reescribe los componentes función como componentes clase durante el build, y que el template de un componente se ejecuta una sola vez. Todo lo que viene después es un parche, no un re-render.

¿En qué se diferencia el JSX de Gea del de React?

El JSX de Gea se parece al de React, y hay una convención que sí tiene que cambiar: escribe class donde React espera className. Los eventos son más permisivos. El README los escribe como atributos en minúscula tipo click, input y change, pero la comparación con Vue de la documentación confirma que onClick, onInput y onChange también se aceptan, así que los handlers al estilo React se trasladan tal cual. Y ref no recibe un objeto ref: Gea coloca el nodo del DOM directamente en la propiedad del componente una vez terminado el render.

// Hábito de React      // Equivalente en Gea
<div className="card"   <div class="card"
  onClick={save} />       click={save} />

El patrón de ref de la documentación es un campo de clase inicializado a null, ref={this.videoEl} en el elemento y, tras el render, uso directo de this.videoEl.

Props: los objetos son el proxy del padre

La mayor desviación respecto a React y Vue es lo que ocurre con una prop no primitiva. La documentación de componentes de Gea explica que el hijo recibe exactamente el mismo proxy que tiene el padre, de modo que cualquier escritura que haga el hijo aterriza en el estado del padre y se refleja en el DOM del padre. Los primitivos se comportan como los argumentos de función en JavaScript: el hijo recibe una copia, y reasignarla no cambia nada fuera del hijo. La documentación muestra a un hijo haciendo justamente esto:

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>
  }
}

La regla se mantiene por muy profundo que sea el árbol. Pasa la misma referencia a un nieto, deja que escriba en el objeto y todos los ancestros que observan esos datos se redibujan. No hace falta elevar nada con un callback, y no hay un paso intermedio con emit o v-model.

El hijo actualiza al padreReactVueGea
Objetos/arraysProps de callbackemit / v-modelMutación directa del proxy compartido
PrimitivosProps de callbackemit / v-modelNo es posible (paso por valor)

La documentación presenta esto únicamente como una ventaja, y las preguntas abiertas quedan sin responder. En un árbol de 40 componentes, ¿qué componente mutó este objeto? La convención unidireccional de React existe en parte para que los cambios tengan un origen rastreable; Gea cambia eso por inmediatez, y todavía nadie ha documentado cuánto cuesta esa contrapartida a escala. Lo mismo vale para el cableado en tiempo de compilación en sí: cómo maneja el compilador el código que no puede analizar estáticamente es algo que la documentación no aborda.

Tamaño y velocidad, según los reporta el proyecto

Toda cifra de rendimiento sobre Gea es una medición propia del proyecto contra los builds que el propio mantenedor hizo de los frameworks competidores. Las tablas de tamaño del README sitúan una app hello world en 121 B de JavaScript en brotli, frente a los builds del proyecto de Solid (3,6 kb), Svelte (8,5 kb), Vue (20,7 kb) y React (50,8 kb), con el todo interactivo en 4,9 kb. Ambos conjuntos de cifras se tomaron en Gea 1.3.0 a partir de builds de producción recientes con Vite 8.0.10.

La puntuación de 1,02 en js-framework-benchmark, donde 1,00 es JavaScript vanilla escrito a mano, procede de la ejecución de la suite realizada por el propio proyecto en Chrome 147, no de una ronda oficial publicada. La frase “el framework de UI compilado más rápido” de la página de inicio es una afirmación del proyecto construida sobre esas mismas cifras autoejecutadas, no un hallazgo de terceros.

¿Qué se distribuye junto con Gea?

La tabla de paquetes del README lista @geajs/core, @geajs/vite-plugin, @geajs/ssr para renderizado en servidor, create-gea para el scaffolding, además de @geajs/ui (componentes headless construidos sobre Zag.js) y @geajs/mobile para primitivas móviles. gea-tools es una extensión de VS Code y Cursor, no un paquete de npm.

La entrada más inusual es el tooling de IA. Ejecutar npx skills add dashersw/gea instala un conjunto de agent skills que viven en el repositorio bajo .cursor/skills/gea-framework y le entregan a un asistente de programación con IA las convenciones que de otro modo tendría que adivinar: cómo funcionan los stores, cómo se declaran los componentes y en qué se diferencia el JSX. Para un framework joven sobre el que ningún modelo tiene datos de entrenamiento, distribuir las convenciones como skills consumibles por el editor es una medida pragmática de onboarding.

Madurez: qué te dicen los números de versión

Las tablas de comparación y de tamaño del README están medidas en Gea 1.3.0, y @geajs/core ha publicado desde entonces la 1.4.0 según las notas de versión del proyecto. Gea tiene licencia MIT y lo mantiene una sola persona, Armagan Amcalar. Todas las cifras de benchmark y de tamaño son autorreportadas, y aún no existe ninguna revisión técnica independiente del framework. Para un equipo, la conclusión es sencilla: el modelo es coherente y lo bastante pequeño como para evaluarlo en una tarde, pero un único mantenedor, un número de versión temprano y cifras no verificadas significan que todavía no hay base de evidencia para apostar un producto por él.

La afirmación genuinamente interesante de Gea no es el tamaño del bundle; es que clases planas, funciones y getters pueden sostener un modelo de reactividad completo si un compilador se encarga del cableado. La forma más rápida de juzgar esa afirmación es montar el contador y el ejemplo de props de arriba y ver si la semántica bidireccional de objetos se siente como claridad o como un lastre para la depuración en tu tipo de base de código.

Preguntas frecuentes

¿En qué se diferencia Gea de Solid y Svelte?

Los tres se apoyan en un compilador, pero la primitiva reactiva difiere. Solid construye la reactividad sobre señales que se ejecutan en el navegador, y Svelte 5 usa su sintaxis de runes compilada desde su propio lenguaje de plantillas. Gea no tiene ninguna de las dos: el estado se guarda en clases planas que envuelve un proxy profundo, y un plugin de Vite lee JSX estándar en tiempo de build para conectar parches directos al DOM.

¿Qué hooks de ciclo de vida tienen los componentes de Gea?

Los componentes clase de Gea exponen cuatro hooks. created(props) se dispara entre el constructor y el primer render, y es donde la documentación coloca la lógica de inicialización. onAfterRender() se ejecuta una vez que el elemento del componente está en el documento y sus hijos se han montado. onAfterRenderAsync() espera al siguiente requestAnimationFrame. dispose() retira el componente del DOM y desmonta sus observers e hijos. La documentación te dirige a los componentes clase siempre que necesites cualquiera de estos.

¿Funciona Gea con TypeScript?

Sí. Un componente clase declara la forma de sus props con 'declare props', una declaración ambiente que no emite JavaScript pero permite que cualquier editor con soporte de TypeScript autocomplete y verifique los atributos, sin ningún plugin del framework de por medio. Anotar el parámetro de template() como this['props'] propaga esos tipos a las variables desestructuradas dentro del método; si lo omites, caen a any. Los componentes función reciben el mismo tratamiento mediante una anotación de parámetro normal.

¿Cómo inicio un nuevo proyecto con Gea?

Genera el scaffolding con 'npm create gea@latest', la herramienta create-gea del proyecto. Los builds de Gea se apoyan en Vite, y @geajs/vite-plugin es lo que se encarga de la transformación de JSX, el cableado de la reactividad y el hot reloading. La documentación también incluye una guía de uso en el navegador para ejecutar Gea sin paso de build, junto con guías para el router, el kit de UI y los paquetes móviles.

DevTools for the frontend

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

We use cookies to improve your experience. By using our site, you accept cookies.