Most reactive frameworks do their work at runtime: they build a virtual DOM, diff it against the previous render, and patch the real DOM. Olum takes a different path — the compiler does as much work as possible at build time, leaving the runtime with almost nothing to do.
Static analysis of templates
When Olum compiles a .olum file, it parses the template into an AST and annotates every node with its reactive dependencies. A node that depends on no signals is marked static and compiled to a plain DOM creation call — it will never be compared or patched again.
// Input template
<div class="card">
<h1>Hello, {name}</h1>
<p class="static-text">This never changes.</p>
</div>
// Compiled output (simplified)
const _static = _createStaticNode('<p class="static-text">This never changes.</p>')
function render(name: Signal<string>) {
const h1 = _el('h1')
_effect(() => _setText(h1, name.value))
return _div('card', [h1, _static])
}The reactive graph
For dynamic nodes, the compiler generates direct signal subscriptions rather than a render function. When a signal changes, exactly the DOM nodes that depend on it are updated — no diffing, no component re-render, no work for anything else in the tree.
What this means in practice
- No virtual DOM allocation on every render
- Static subtrees are created once and never touched again
- Updates are O(1) per changed signal, not O(n) for the subtree
- The runtime ships at 8kb gzipped — most of it is the scheduler
If you're curious about the compiled output for your own components, run olum build --inspect. It writes human-readable compiled JS alongside your bundles.
Priya Mehta
Compiler Engineer · Olum Team