The same counter, in each library

This is the component behind the comparison guide: one minimal counter — a single reactive count prop, a click handler, a re-render on change — implemented in web-component-base and in each library it's measured against. Every counter below is live; click it. The source of each is listed at the bottom of the page, and the measurement that produces the sizes is measure.mjs, runnable from this folder.

web-component-base 2.6 kB brotli
static props + html
Elena 3.4 kB brotli
click handler wired in firstUpdated
Lit 5.3 kB brotli
static properties, shadow DOM
FAST 12.2 kB brotli
binding directives, shadow DOM
vanilla HTMLElement ~0.2 kB brotli
no library — the hand-rolled baseline

How it's measured

The number that matters for a first component is not the library's advertised size — it's library runtime + your component code, bundled and compressed, because that's everything the browser actually downloads. So measure.mjs, for each library:

  1. bundles the counter with its library runtime using esbuild (bundle: true, minify: true, format: 'esm') — tree-shaking away whatever that component doesn't touch;
  2. compresses the bundle with gzip (level 9) and brotli (quality 11) via Node's built-in zlib — the same codecs a CDN or server serves with.

The counters are byte-for-byte the same components running above and listed under Implementation below. The external libraries are pinned dev dependencies of this demo workspace, and web-component-base is bundled from its published dist/, so the run is deterministic.

Output

Measured at the pinned versions below (WCB from this repo's build, esbuild 0.27, Node zlib):

Library Version Minified Gzip Brotli
web-component-base 6.1.4 6.6 kB 2.9 kB 2.6 kB
@elenajs/core 1.0.0 9.1 kB 3.7 kB 3.4 kB
lit 3.3.3 15.3 kB 5.9 kB 5.3 kB
@microsoft/fast-element 3.0.1 44.8 kB 13.6 kB 12.2 kB
vanilla HTMLElement 0.6 kB 0.3 kB 0.2 kB

The WCB counter is the smallest real component here — about 23% under Elena, 52% under Lit, and 79% under FAST once compressed.

Reproduce it

From demo/examples/library-comparison/: node measure.mjs for the table, node measure.mjs --md for Markdown, or node measure.mjs --json for raw numbers.

Bump a pinned version in demo/package.json, re-run, and the numbers move with it — the benchmark is the source of truth, not this page.