Framework benchmark posts have a credibility problem: the author's framework wins. So this post is built the other way around. It describes how AngeLite is benchmarked, what the numbers show, and, more importantly, where the project's own comparison says it loses.
Method first
The benchmark is a table app: table > tbody > tr with 3 cells, one click handler per row, and the selected row marked with a class. The data comes from the same deterministic generator in every implementation. Each framework is written idiomatically:
-
React 19 with
memo+useCallback -
Preact (core + hooks only,
shouldComponentUpdateon the row) -
Vue 3 with a compiled template and
shallowRef -
Angular 20 with signals,
OnPush,@for ... track, and zoneless change detection -
AngeLite with signals and
@for ... track, in two modes: compiled in the browser, and precompiled
What's measured: performance.now() from triggering an operation until a DOM condition holds (for example "there are 1,000 rows") and style + layout has been forced. It does not include painting. Two warm-up iterations are discarded per operation, and rounds alternate framework order. Bundles are built with each framework's usual tool (esbuild, Vite, ng build).
Run on a shared container with no CPU throttling, so absolute numbers aren't comparable; positions within a run are. The project uses a "within 10% is a tie" rule because differences of a few milliseconds are noise.
cd benchmarks
npm install
npm run build # builds the 5 apps
npm run bench # runs the suite -> benchmarks/results.json
What it shows
| Precompiled AngeLite | Best of the others | |
|---|---|---|
| App size (gzip) | 6.1 KB (smallest) | Preact 6.2 KB |
| Startup | 23.1 ms | Preact 21.3 ms (technical tie: overlapping interquartile ranges) |
| Memory, 10,000 rows | 6.6 MB | Angular 11.8 MB |
| 12 measurements in all | lowest median in 7; within 10% in 4; behind in remove (Preact, +16% in that run) |
n/a |
Overall score, as the geometric mean of time relative to the best per operation: 1.03x for precompiled AngeLite; React at 1.55x. Where AngeLite wins clearly: size, memory and list speed. And in "no build" mode it's the only one with a small option: about 10 KB gzip, versus Vue's 63.7 KB with its compiler, and with no eval.
Repeat-run honesty: swap and remove vary between runs. Two dedicated repetitions gave 4.70 ms vs Preact's 4.90, and another 4.75 vs 4.70. The project's own reading is "a tie with Preact and Angular", not a win.
What it doesn't measure
The page says it plainly: SSR, hydration, ecosystem, DevTools, accessibility, mobile performance and long-term memory behaviour aren't covered. "Angular and React offer much more than AngeLite; this compares only the rendering core."
The comparison: where it loses
Alongside the benchmark there's a feature-by-feature comparison table with a source for each cell:
- V: verified by running the code or reading the installed package (React 19.3.1, Preact 10.29.8, Vue 3.5.44, Angular 20.3).
- D: from official documentation.
- G: general knowledge that wasn't checked, flagged for review before quoting.
Of the table's rows, 16 are V, 2 are D and 19 are G, and the security rows are almost all V. Scoring features on a simple scale, AngeLite lands at 19.5 against 24.5 (Preact), 27 (Vue), 28.5 (React) and 33 (Angular). The document is explicit: "It is not a ranking, but the gap is real."
Where it loses is everything around the core:
| Missing or immature | Who has it |
|---|---|
| Compile-time optimisations (hoisted static subtrees, folded constants, per-node flags) | Vue, React Compiler, Angular AOT |
| Concurrent rendering and transitions | React (and the recommendation here is not to copy it: the complexity is enormous for a lightweight framework) |
| Incremental hydration and adopting server nodes | React, Vue, Angular |
| Editor language service / template autocompletion | Angular, Vue |
Browser DevTools extension, async validators, FormBuilder
|
Angular and others |
| Years of security review and a community | All of them |
| Types and template checking | Today the .d.ts is checked, but templates are checked for elements, pipes and names, not types |
Limits of its own design (verified in the code)
- One effect per view, not per binding. In a component with hundreds of bindings and a hot signal this can cost; Vue and Solid are finer.
- Immutable lists. Identity is compared; mutate-in-place-and-reassign-the-same-array doesn't update.
- Measurement noise. Shared container, no painting; differences under 10% aren't conclusive.
Why publish this?
Three reasons:
- It makes the wins believable. If a document says "we lose here, and here, and here", the claim "we're smallest" gets read as measured, not marketed.
- It prevents the wrong adoption. The best outcome of an honest comparison is someone deciding React or Angular is the right call for them.
-
It's a roadmap. The gap table is the backlog, ordered by value (see the project's ROADMAP: hydration that adopts existing nodes and streaming rendering, route and list animations,
FormBuilderand async validators, editor autocompletion, i18n message extraction, template type-checking).
Reproduce it, and argue
Everything is in the repo: the apps, the harness, the raw JSON results and the security probe (npm run probe:security in benchmarks/). If a number is wrong, or an idiomatic implementation of your favourite framework is unfair, a PR is more useful than an argument.
Takeaways
- State the method, the noise and the non-goals before the table.
- Use a tie rule (here, 10%) and say when a result flips between runs.
- Label every claim by how it was verified.
- Put the losses in the same document as the wins.
Next: the one feature that stresses all of this at once, server-side rendering, and why "the blueprint is data" makes it a natural next step.
Top comments (0)