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.2 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)
Server rendering⚠️ no SSR package; typed prop state initializes from server-written attributes (any server, no server-side JS)@lit-labs/ssr (carries labs prerelease notice)⚠️ @elenajs/ssr is experimental alpha⚠️ fast-ssr deprecated; successor packages pre-1.0
Hydrates server DOM❌ first client render replaces server markup❌ dynamic components replace server markup on first render⚠️ defer-hydration exists, tied to deprecated/pre-1.0 stack
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; one package, small surfaceOpenJS 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?.


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.