Introducción
Qué es Ascua
Un framework de UI sin Virtual DOM. Escribes HTML dentro de TypeScript, un compilador en WebAssembly lo traduce a operaciones de DOM, y al navegador llegan 2,23 kB de runtime.
La idea en una pantalla
import { signal } from "ascua";
function Contador() {
const cuenta = signal(0);
return view`
<button onclick=${() => cuenta.update((c) => c + 1)}>
Clicks: ${() => cuenta()}
</button>`;
}Eso es HTML de verdad —onclick, no onClick— dentro de una plantilla de
TypeScript. view no existe en tiempo de ejecución: el compilador la sustituye
por las llamadas que construyen ese botón, y pone un efecto en el único punto
que lee un signal, el texto. Cuando cuenta cambia, ese efecto escribe en ese
nodo de texto. No se vuelve a ejecutar la función, no se construye un árbol
nuevo y no se compara con el anterior.
Por qué sin Virtual DOM
Un framework con Virtual DOM responde a un cambio reconstruyendo una representación del árbol y comparándola con la anterior para deducir qué tocar. El trabajo es proporcional al tamaño del árbol, no al del cambio.
Ascua establece una sola vez, al compilar, la relación entre cada dato y el nodo que lo muestra. A partir de ahí, cambiar el dato ejecuta directamente la operación de DOM que le corresponde. No hay nada que deducir porque nada se olvidó. Es el mismo modelo que Solid o Svelte 5; lo que cambia es dónde vive cada pieza.
Las tres ideas
1. Una closure es reactiva; todo lo demás, no. ${() => cuenta()} sigue al
signal; ${cuenta()} se evalúa una vez. Se sabe qué puede cambiar mirando la
plantilla, sin conocer los tipos. Está en Plantillas.
2. HTML, no JSX. Los atributos son los del HTML, el marcado se copia y se
pega tal cual, y un <style> dentro de la plantilla es CSS con scope que se
extrae al compilar. Está en Estilos.
3. WebAssembly donde suma. El compilador está escrito en Rust y se
distribuye como un único .wasm de 87 KB que corre en Node, Bun, Deno y el
navegador —el playground es ese mismo archivo—. En el
navegador, en cambio, el DOM vive en JavaScript y cruzar la frontera cuesta más
que la operación, así que el runtime es JavaScript. Está en
Cómo funciona.
Lo que trae
| Paquete | Qué es | gzip |
|---|---|---|
ascua |
Signals, operaciones de DOM, SSR e hidratación | 2,23 kB |
ascua-router |
La ruta como signal, con parámetros y enlaces que no recargan | 0,98 kB |
ascua-testing |
Montar, tocar y desmontar un componente en un test | — |
vite-plugin-ascua |
Compila las plantillas y entrega el CSS a Vite | — |
ascua-compilador |
El compilador, como módulo WebAssembly | — |
Una aplicación entera —runtime, un contador y una lista con clave— pesa 2,43 kB gzip. Un panel con acceso, rutas, tabla filtrable y componentes, 5,69 kB más 1,39 kB de CSS.
Cuándo encaja, y cuándo no
Encaja si quieres que el HTML se lea como HTML, que el bundle se mida en kilobytes de un dígito y que cada pieza se pueda auditar en una tarde: el runtime son tres archivos y el modelo reactivo cabe en una página.
No encaja si necesitas el ecosistema de React —sus componentes, sus hooks, JSX— o Server Components: son no-objetivos, no cosas pendientes.
Por dónde seguir
- Primeros pasos: instalar, configurar Vite y montar el primer componente.
- Reactividad:
signal,memoyeffect, que es todo el modelo. - SSR e islas: páginas que llegan hechas desde el servidor y se activan en el cliente.