Eleva.js – A 2.3KB JavaScript framework with signals and no virtual DOM
1 comments
I know this is a thing of taste, but have you considered a syntax closer to SolidJS's approach? Something that feels a bit more vanilla JavaScript, where signals are just tuples with getter/setter and you use JSX instead of template strings and components are just plain functions?
For comparison, here's how this example would look:
For comparison, here's how this example would look:
import { render } from "solid-js/web";
import { createSignal } from "solid-js";
function Counter() {
const [getCount, setCount] = createSignal(0);
return <button => setCount(getCount() + 1)}>{getCount()}</button>;
}
render(() => <Counter />, document.getElementById("app"));
I've been working on Eleva.js, a minimalist frontend framework that just hit v1.0.0.
What it is: A 2.3KB (gzipped) vanilla JavaScript framework with signal-based reactivity and direct DOM patching.
Why I built it: I wanted something between writing raw DOM manipulation and using React/Vue. No JSX, no compiler, no virtual DOM — just native template literals and a simple reactivity primitive.
The mental model is intentionally small:
Technical choices:
- Signals for reactivity (similar to Solid/Preact signals) - Direct DOM diffing instead of virtual DOM - Render batching via queueMicrotask - No build step required — works with native ES modules - ~0.5KB/row memory overhead in Chrome benchmarks
Trade-offs:
- No SSR yet (client-side only) - Template strings aren't as composable as JSX - Smaller ecosystem than established frameworks
Links:
- Docs: https://elevajs.com - GitHub: https://github.com/TarekRaafat/eleva - npm: npm install eleva
Happy to answer questions about the implementation or design decisions.