ascua
v0.5.0
Published
Runtime reactivo de Ascua: signals, effects y operaciones directas de DOM. Sin Virtual DOM.
Maintainers
Readme
ascua
Reactividad fine-grained y operaciones directas de DOM, en 3,62 kB gzip y sin dependencias. Es el runtime de Ascua, y también una librería de signals que se puede usar sola.
stil add ascua # o npm install ascuaSignals
import { signal, memo, effect, batch } from "ascua";
const precio = signal(1000);
const cantidad = signal(3);
const total = memo(() => precio() * cantidad());
effect(() => console.log(total())); // 3000
batch(() => { // un solo recálculo, no dos
precio.set(1200);
cantidad.set(2);
}); // 2400Escribir en un signal no ejecuta nada: marca. Los efectos afectados se encolan y corren cuando la marca termina de propagarse, así que un grafo en diamante no deja leer valores intermedios y una rama cuyo valor no cambió no recalcula.
DOM
Las mismas llamadas que emite el compilador de Ascua, y que se pueden escribir a mano:
import { element, dynamicText, on, append, mount } from "ascua";
function Contador() {
const cuenta = signal(0);
const boton = element("button");
on(boton, "click", () => cuenta.update((c) => c + 1));
append(boton, dynamicText(() => `Clicks: ${cuenta()}`));
return boton;
}
mount(document.body, Contador);show sustituye una región, list reconcilia por clave —conservando el nodo
de cada clave, y con él el foco y el scroll—, attribute y property atan un
atributo o una propiedad a una expresión.
SSR e islas
El mismo código renderiza en el servidor, sin navegador ni dependencias, y el cliente adopta los nodos en vez de rehacerlos:
// las islas, compartidas por servidor y cliente
import { defineIsland, p } from "ascua";
export const IslaContador = defineIsland("contador", { inicial: p.number }, Contador);
// servidor
import { collectStyles, renderToString } from "ascua/server";
const html = renderToString(() => IslaContador({ inicial: 3 }));
const css = collectStyles(html); // el CSS con scope de lo que aparece
// cliente
import { hydrate } from "ascua";
hydrate([IslaContador]);
// { adopted: 4, created: 0, unmount }Los props viajan como JSON y se comprueban contra el esquema antes de hidratar:
si el servidor mandó otra cosa, la isla se queda estática y la consola dice qué
campo falló. island es la pieza de debajo, sin esquema, para quien quiera
otro formato.
hydrate e island suben el runtime a 4,59 kB, y defineIsland unos 0,75 kB
más; lo que no se importa, el tree-shaking se lo lleva. Está explicado en la
documentación.
Con plantillas
Lo normal, de todas formas, es no escribir esto: con
vite-plugin-ascua se
escribe HTML dentro de TypeScript y el compilador lo traduce a estas llamadas.
Licencia
MIT OR Apache-2.0
