Skip to content

wcb vs Lit vs FAST: size and feature comparison

The releases since v5 gave the WebComponent base class a stricter compliance with custom elements specifications, quality of life improvements, and overall robustness by combining JS components authoring expectations and stable HTML behaviors. We now have in-place re-rendering, HTML boolean semantics and overrideable attribute converters, among other improvements.

This page puts these benefits and their cost in context: how much does WCB weigh in size compared to similar web-component libraries, what does each library buy you over writing custom elements from scratch, and when is WCB the right choice.

Measured size: the same component in each library

Section titled “Measured size: the same component in each library”

Numbers below are measured from the same minimal counter component (one reactive count prop, a click handler, a re-render on change) written in each library, bundled with esbuild --bundle --minify --format=esm, and compressed with gzip (level 9) and brotli (quality 11). This is the real “cost of your first component”: library runtime + component code, everything the browser downloads.

See it live: Library comparison demo ↗ — every counter running side by side, the source of each, and the measure.mjs script that produces the table below.

LibraryVersionMinifiedGzipBrotli
web-component-base6.2.06.6 kB2.9 kB2.6 kB
@elenajs/core1.0.19.1 kB3.7 kB3.4 kB
lit3.3.315.3 kB5.9 kB5.3 kB
@microsoft/fast-element3.0.144.8 kB13.6 kB12.2 kB
vanilla HTMLElement-0.6 kB0.3 kB0.2 kB

For scale: even after all of the v5.2–v6.2 work, the WCB counter is ~23% smaller than Elena, ~52% smaller than Lit, and ~79% smaller than FAST.

What each library gives you beyond extending directly from HTMLElement, the boilerplate you no longer write by hand:

CapabilityWCB 6.2Lit 3.3Elena 1.0FAST 3.0
Declarative templateshtml tagged templates (htm) or plain stringslit-html tagged templateshtml tagged templates✅ typed templates with binding expressions
Reactive props ⇄ attributesstatic props, overrideable convertersstatic properties with convertersstatic props, opt-in reflection@attr / observables
Update strategyIn-place patch (index-based, non-keyed)Part-based: only touched bindings update, keyed repeatBatched re-rendersFine-grained observable bindings, keyed repeat
Preserves DOM state on re-render
Update batching / scheduling⚠️ renders per prop write✅ async batched, updateComplete✅ batched, updateComplete✅ queued/batched
Keyed list reconciliation⚠️ positionalrepeat directive⚠️ positional morphrepeat with recycling controls
Light DOM by default✅ (shadow DOM opt-in via static shadowRootInit)❌ shadow DOM by default✅ (shadow opt-in)❌ shadow DOM by default
Scoped styles⚠️ static styles needs shadow opt-in via static shadowRootInit✅ shadow-scoped CSS (shadow DOM is the default)✅ light DOM via generated @scope CSS files (CLI); static styles needs shadow opt-in✅ shadow-scoped + design tokens (shadow default)
SSR / hydration story⚠️ typed prop state from attributes — any server, no server-side JS; client re-renders⚠️ @lit-labs/ssr + hydration (labs = prerelease)⚠️ experimental alpha; client re-renders⚠️ experimental SSR
Works with zero build tooling✅ import from CDN, no compiler✅ (buildless possible, decorators need tooling)⚠️ practical with tooling
Editor/IDE tooling✅ typed props + CEM analyzer plugin✅ extensive (analyzer, TS decorators, IDE plugins)✅ CEM-focused✅ TS-first
Lifecycle hooksonInit, afterViewInit, onChanges, onDestroyfull reactive update lifecyclewillUpdate, firstUpdated, updatedfull lifecycle + behaviors
Backing / ecosystemsolo maintainer, intentionally small surface in one packageOpenJS Foundation (donated by Google 2025), large ecosystemnew (2026), solo-authoredMicrosoft, powers Fluent UI

For what these numbers and capabilities add up to (and when they don’t) see Why would anyone use WCB?.

Three of the four SSR cells quote that package’s own stability designation. @lit-labs/ssr is the most mature; though it has carried Lit Labs’ pre-release notice (“may receive breaking changes or stop being supported”) since 2021, it sits at major version 4, ships actively, and drives a maintained Eleventy integration. @elenajs/ssr is an alpha and says so, and FAST calls its own SSR experimental.

WCB has no SSR package at all, so its ⚠️ means something different from the other three. The state half already works: every declared prop initializes from server-written attributes, parsed through its declared type, from any server that can print HTML. The DOM half does not — the first client render replaces the server markup rather than adopting it, so the server HTML is paint-only. @elenajs/core behaves the same way as WCB here: a dynamic component’s first client render replaces the server markup rather than adopting it.


All libraries measured 2026-08-09 — WCB at v6.2.0 — with esbuild, Node zlib (gzip −9, brotli q11), at the pinned versions above. Methodology: identical counter component per library, bundled per library, compressed. Re-run them yourself — the counters and the measure.mjs script live in the demo workspace (demo/examples/library-comparison/). The benchmark is trivially reproducible with the versions pinned above.