# krausest/js-framework-benchmark: what the table actually measures

> The js-framework-benchmark runs the same keyed table operations across 186 framework implementations and reports duration including rendering time. The hard part is not the numbers, it is deciding which of them apply to your app.

**krausest/js-framework-benchmark** — A comparison of the performance of a few popular javascript frameworks

- Repository: https://github.com/krausest/js-framework-benchmark
- Website: https://krausest.github.io/js-framework-benchmark/
- Stars: 7,486 · Forks: 941
- Language: JavaScript
- License: Apache-2.0
- Published: 2026-09-22 · Updated: 2026-09-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/krausest-js-framework-benchmark

## The problem it solves: one table, many frameworks

Framework performance claims are usually made on different hardware, with different workloads, by people with different incentives. This repository replaces that with a single operation set that every implementation has to perform. The README lists the operations: create rows, replace all rows, partial update, select row, swap rows, remove row, create many rows, append rows to large table, clear rows, plus memory measurements (ready, run, update, replace, repeated clear) and Lighthouse-derived figures such as startup time, consistently interactive, script bootup time, main thread work cost and total byte weight.

The audience is narrow on purpose. This is for people who maintain a framework, or who have to justify a rendering-layer choice with something more defensible than a conference talk. The README is explicit that duration is measured including rendering time, and that the wiki article How the duration is measured carries the details. If your workload is not a large, mutable table, the benchmark is measuring a neighbour of your problem, not your problem.

## Keyed versus non-keyed decides what the numbers mean

The most useful part of the README is not the operation list, it is the keyed versus non-keyed explanation. In keyed mode you assign an identifier from the data as the key, so each data item maps to one DOM node and reordering the list reorders those nodes. In non-keyed mode, which the README says vue.js uses by default for lists, a data change can modify DOM nodes that previously belonged to other data. For React and Angular, using the item index as the key is non-keyed mode.

That distinction changes the cost profile. The README states non-keyed can be more performant because costly DOM operations are avoided, and that it can also cause severe problems. So a framework's position in the table is partly a statement about which mode its implementation chose. Comparing a keyed implementation against a non-keyed one and calling the difference a framework difference is the mistake this section exists to prevent.

Starting with Chrome 118 the overall performance figure is computed as a weighted geometric mean, per the README's link to the wiki page on that computation. A geometric mean of ratios is a reasonable way to combine operations with different units, but it also means one very slow operation drags the whole score rather than being averaged away.

## Running the pre-built binaries instead of building 186 implementations

The README opens its instructions with a security advice: there are 186 implementations, the author cannot assess them all, and npm ci and npm install can execute arbitrary commands. The recommended path is to download the prebuilt build.zip for a chrome release and skip installing packages for every implementation. The author states they build on a dedicated virtual private Linux server for that reason.

Prerequisites are node.js >= v20.9.0, with npm and node --version checked before building. The README says the benchmark has been tested with node v20.9.0.

```bash
node --version
npm --version
```

The README shows node v20.9.0 and npm 10.1.0 as the expected output of that check. If you see something older, stop there.

The workflow is checkout a tagged release, then start the server. The README's example begins with cloning the repository and picking a release such as chrome 100:

```bash
git clone https://github.com/krausest/js-framework-benchmark.git
cd js-framework-benchmark
git checkout chrome100
```

The repository's package.json defines the scripts that drive the rest. npm start changes into server and starts it, npm run bench changes into webdriver-ts and runs dist/benchmarkRunner.js with LANG set to en_US.UTF-8, and npm run results produces the results. npm run bench-all chains the last two.

```bash
npm run install-local
npm start
```

install-local runs install-webdriver-ts, install-webdriver-ts-results and install-server in sequence, per package.json. The README's security advice is the reason to prefer the prebuilt zip over this path when you only want to read results rather than add an implementation. The README also states the server should only be started on your local machine and that access should be restricted to your local machine, with an explicit recommendation against exposing it to the internet.

## Where the benchmark misleads you

The snapshot page is the weak point, and the README says so. The current snapshot "may not have the same quality", results might be for mixed browser versions, and the number of runs per benchmark may vary. That is a different artifact from the official results page and from a tagged release. Quoting a snapshot number in a design document without checking which release produced it is a real failure mode.

The second limitation is coverage. Every operation in the list is a table operation: create, replace, partial update, select, swap, remove, append, clear. There is no routing benchmark, no form validation, no server-side rendering comparison, no hydration measurement, and no bundle-size-versus-feature trade-off. A framework that wins here has a fast list reconciler and cheap row updates. That is a genuine signal for data grids, log viewers and dashboards. It says little about an app whose cost sits in data fetching, code splitting or state management.

The third is that memory figures are measured after specific interactions (page load, adding 1,000 rows, five update clicks, five create clicks, five create-and-clear cycles), not under a long-running session. A leak that appears after an hour of navigation will not show up in any of those numbers.

## What to compare it against

The obvious alternative is a synthetic microbenchmark you write yourself, for example a js-framework-benchmark-style loop reduced to the two operations your app actually performs, run against your own component tree with your own data shapes. The difference in approach is scope: this repository fixes the workload so that results are comparable across frameworks and across time, while a custom benchmark fixes relevance to your app but produces numbers nobody else can reproduce or check. If your goal is to pick between two frameworks for one product, the custom benchmark is the better instrument, and this repository is the sanity check afterwards.

A second alternative is a general web performance tool that measures a real page rather than a synthetic table, using Lighthouse or WebPageTest against your own build. This repository already borrows Lighthouse metrics (consistently interactive, script bootup time, main thread work cost, total byte weight), but it applies them to the benchmark page, not to an application. Running Lighthouse on your own page gives you the same metric family with your real DOM, your real CSS and your real third-party scripts. The trade-off is that you lose cross-framework comparability entirely, because nobody else has your page.

## Maintenance, licence and what a run costs you

The repository is not archived and the last push was on 2026-09-20. Releases track Chrome versions: chrome152 on 2026-09-01, chrome150 on 2026-07-05, chrome148 on 2026-05-10. That cadence matters for upgrade cost, because a benchmark whose results are tied to a browser version needs re-running when the browser moves. If you pin to a tagged release, you are pinning to a Chrome version as well as a code state.

The licence is Apache-2.0, which permits commercial use and modification with the usual attribution and notice requirements. That covers the benchmark harness in this repository. It does not cover the 186 framework implementations under frameworks/, which carry their own licences, and it does not cover the prebuilt build.zip contents. If you intend to vendor any implementation into a product, check that implementation's own licence rather than assuming the repository licence applies. This is a description of the licence file, not legal advice.

The operational cost is the part people underestimate. Building all implementations is described in the README as challenging, which is why the prebuilt route exists. Running the full benchmark means a browser under WebDriver control, a local server, and enough time for repeated iterations across every operation. The README's own answer to this is to build on a dedicated machine and to keep the server off the public internet.

## Conclusion

Adopt it if you need a reproducible, same-machine comparison of client-side rendering and update cost for a specific framework version, and you are willing to run the server locally and read the keyed versus non-keyed distinction before quoting any number. Do not adopt it as a general verdict on framework quality, and do not run it on a shared or internet-facing host: the README states the server should only be started on your local machine and that npm install can execute arbitrary commands across 186 implementations. Before you cite a result, verify which benchmark mode the implementation uses and whether the snapshot page or the tagged release produced it, because the README says the current snapshot may mix browser versions and vary the number of runs per benchmark.

## FAQ

### Which JS framework is fastest according to krausest/js-framework-benchmark?

The repository does not declare a single winner in its README. It publishes an official results page and a snapshot page, and starting with Chrome 118 the overall performance is computed as a weighted geometric mean across the operations, so the ranking depends on the browser release you look at.

### What is the best JS framework in 2026?

This benchmark cannot answer that. It measures table operations such as create rows, replace all rows, partial update, select row, swap rows and remove row, plus memory and Lighthouse-derived metrics, all on a synthetic table rather than on an application.

### What are the top 5 JavaScript frameworks?

The README does not rank frameworks into a top five. It states that there are currently 186 implementations in the repository and lists the operations each one is measured on.

### Why is everyone suddenly ditching JavaScript frameworks?

The README does not discuss framework adoption or abandonment. It describes a benchmark for client-side rendering performance and the keyed versus non-keyed list modes, and it does not comment on migration trends.

## Sources

- [krausest/js-framework-benchmark on GitHub](https://github.com/krausest/js-framework-benchmark)
- [License: Apache-2.0](https://github.com/krausest/js-framework-benchmark/blob/master/LICENSE)
- [Project website](https://krausest.github.io/js-framework-benchmark/)
- [README](https://github.com/krausest/js-framework-benchmark/blob/master/README.md)
- [Releases](https://github.com/krausest/js-framework-benchmark/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/krausest-js-framework-benchmark
