Skip to content
ivue — Infinite Vueivue — Infinite Vue

Plain classes.Full reactivity.Infinite scalability.One kilobyte.

Native TypeScript classes become fine-grained Vue 3 state. No proxy per instance. No decorators. No component coupling. Nothing paid until first access.

count
0
double (plain getter)
0
watchwaiting for the first change
Live. This counter is a Reactive() class instance, running the same 1 kB engine that ships.
1.1kb
the whole engine, gzipped
0
dependencies
100%
test coverage, every metric
22 ms
to create 1 million instances

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.

Antoine de Saint-Exupéry

Hard problems, solved together

Each of these sank earlier class-reactivity attempts. Solving one or two is easy. ivue ships all of them as one coherent design.

Bound methods

this.method is always correct, always the same reference. The wrapper-arrow era ends.

Reactive inheritance

Deep super.x.value chains resolve level-safe. Reactivity flows through every layer.

Development parity

The same class identity, direct method binding, and engine branches run in development and production.

Circular import immunity

The namespace pattern resolves mutual references in any load order.

Writable getter types

Ref-returning getters type as writable. Instances are fully inferred.

Deterministic teardown

$watch scopes per instance, $stopEffects cleans up. Pure data pays nothing.

Minimal memory footprint

Derivations are shared prototype getters, not per-instance allocations.

Hot paths

Reads hoist to native ref speed with one line where it matters.

One idea, carried through

Reactive() transforms a class once — the prototype, not the instances. Ref-getters become state, created on first touch. Plain getters re-derive on every read, reactive with zero allocation. Methods bind once, to the right this. Instances stay ordinary objects: a plain new, no proxy, nothing paid until first access.

Everything else falls out of that one move — inheritance, development parity, deterministic teardown, speed. Not features bolted on; consequences of where things live.

Cart.ts
ts
import { Reactive } from 'ivue'
import { ref } from 'vue'

class $Cart {
  get items() {
    return ref<{ price: number }[]>([])
  }
  get total() {
    return this.items.value.reduce((sum, item) => sum + item.price, 0)
  }
  add(price: number) {
    this.items.value.push({ price })
  }
}

export namespace Cart {
  export const $Class = $Cart // raw — children `extends` this
  export let Class = Reactive($Class) // reactive — you `new` this
  export type Instance = typeof Class.Instance // expose & reactive() interop
}

const cart = new Cart.Class()

Start here

Performance numbers

Measured, not promised.

ivue vs the World → — ivue against the alternatives, head to head.
Performance by Design → — method and full tables.
Interactive Benchmarks → — five live benchmarks, running in your browser.

Best measured result among fully reactive implementations. Non-reactive controls mark the floor.

Creating 1,000,000 instances

timeivue is
ivue new Class()21.7 ms the baseline
composable factory139 ms6.4× faster
native reactive()470 ms22× faster
eager class engine (unreleased v1)2,861 ms132× faster

Refs and computeds do not exist until first access. Median of runs with every instance retained.

Memory heap at 100,000 instances

per live instance100k total
ivue class, 30 getters3.7 KB 364 MB
composable, 30 closures8.0 KB781 MB
reactive(), fields + getters10.4 KB1.02 GB
composable, 30 computeds19.7 KB1.93 GB

Every instance observed by its own effect — live, not at-rest. Derivations live on the prototype; they weigh nothing per instance.

Proxy-free reads

The standard uses raw instances. Measured on Node 22, V8 and Vue 3.5 over 10-million-iteration loops, ordinary ivue access stays below both proxy alternatives:

access pathivue rawshallow proxyreactive()
plain derived getter23.4 ns68.2 ns125.1 ns
ref-getter access9.6 ns47.0 ns72.4 ns
method access3.8 ns42.3 ns68.5 ns

A direct closure ref remains faster than a dotted property read. Stable ivue refs and methods hoist once outside a hot loop, reducing repeated access to the same direct-handle path.

What a live cell costs at rest

A stress test at document scale: a spreadsheet grid where every cell is live, formula-capable reactive state — built four ways, then weighed.

bytes/cellwhat the cell is
composable (idiomatic Vue)~758closures + eager ref/computeds
ivue instance grid~67plain object + lazy overlay
plain JavaScript object, no reactivity~40{ row, col, raw }
ivue flyweight columnar4.7 1 B kind + 8 B Float64, shared

Measured end-to-end on live grids up to 20,000,000 cells — fully reactive at 8.5× below the plain-object floor. The receipts run in your browser: Interactive Benchmarks →

Released under the MIT License.