跪拜 Guibai
← All articles
Frontend · JavaScript · Programmer

Web Components Still Can't Compete With Frameworks, and the Reason Isn't Technical

By ErpanOmer ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Web Components are often pitched as the future-proof, standards-based alternative to frameworks, but the gap between standards correctness and daily engineering usability means betting on them for a typical project adds cost and slows delivery with no offsetting benefit. The exception is a multi-framework enterprise design system, where framework-agnostic components genuinely reduce duplication.

Summary

Web Components ship with three W3C APIs—Custom Elements, Shadow DOM, and HTML Templates—and promise framework-agnostic reuse. But a simple counter component takes five times more code than React, requiring manual DOM string concatenation, event binding, and re-render triggers. No built-in reactivity means developers must hand-roll state-to-DOM synchronization, which turns complex forms into unmaintainable spaghetti. Shadow DOM's absolute style isolation breaks global theme overrides and utility-class workflows like Tailwind, while the absence of server-side rendering leaves components as empty shells until client JavaScript executes—a non-starter for SEO-sensitive projects. The cross-framework reuse pitch solves a problem most teams don't have, since organizations standardize on a single framework. The one defensible use case is a large enterprise with dozens of teams on different stacks needing a shared design system, which is why GitHub, Adobe, and SAP built theirs on Web Components. For the other 99% of teams, React or Vue remains the cheaper, faster choice.

Takeaways
A counter component takes 3 lines in React and over 15 lines in native Web Components, with manual HTML string building, event binding, and re-render calls.
The Web Components standard includes no reactivity system; state changes require hand-written attributeChangedCallback logic and manual DOM updates.
Shadow DOM's absolute CSS isolation prevents global theme variables and Tailwind utility classes from working unless the component author explicitly exposes every style property.
Server-side rendering is effectively unsupported because customElements.define doesn't exist in Node.js, leaving components as empty tags until client JS loads.
Cross-framework reuse is a pseudo-requirement for most teams, which standardize on a single framework across all projects.
Lit adds reactivity to Web Components but reintroduces framework dependency, undercutting the 'native standard' argument.
GitHub Primer, Adobe Spectrum, and SAP UI5 use Web Components for multi-framework design systems—the only scenario where the trade-offs pay off.
Conclusions

The core tension isn't Web Components versus React; it's that a standard designed by committee optimized for theoretical correctness while frameworks optimized for the developer's clock. Standards bodies can mandate APIs but can't mandate ergonomics.

Lit's existence as the de facto fix for Web Components' missing reactivity is a paradox: if you need a framework to make a standard usable, the standard hasn't actually eliminated the need for a framework.

The cross-framework reuse pitch targets a problem that exists mainly in conference talks, not in team org charts. Most companies enforce stack consistency precisely to avoid the integration pain Web Components claim to solve.

Concepts & terms
Custom Elements
A browser API that lets developers define new HTML tags with custom behavior by extending HTMLElement. Registration happens via customElements.define(), but the API only runs in browser JavaScript engines, not in Node.js.
Shadow DOM
An encapsulation mechanism that attaches a separate DOM tree to an element, isolating its CSS and JavaScript from the rest of the page. Styles inside cannot leak out, and external styles cannot penetrate in—except via CSS custom properties that the component author must explicitly expose.
HTML Templates
The <template> element holds inert HTML fragments that aren't rendered until cloned via JavaScript. Web Components use templates to define reusable markup structures.
attributeChangedCallback
A lifecycle callback in Custom Elements that fires when an observed attribute changes. It is the only built-in mechanism for reacting to property changes, and developers must manually implement DOM updates inside it.
From the discussion

The discussion challenges the premise that cross-team component reuse is a real need, arguing that even a library as comprehensive as antd fails to bridge the communication costs between teams, making business components even less shareable. A separate point contests the article's claim about missing SSR support, asserting that web components already support server-side rendering. Another concern raises the developer experience problem of integrating custom elements with TypeScript, questioning whether parameter passing requires blind memorization.

Cross-team component library reuse is a pseudo-requirement because communication overhead makes it impractical, even for widely-used libraries like antd.
Business components are even less likely to be shared across teams, as each team maintains its own.
Contrary to the article's claim, web components already support server-side rendering.
Custom DOM elements lack seamless TypeScript integration, forcing developers to memorize parameters without type safety.
Featured comments
贾东雷

Big companies are also pseudo-requirements. It's fundamentally impossible for different teams to share a single component library. The communication cost is too high. Take antd as an example. It's supposed to be usable across different teams. But it's still useless. If it's business components, the scenarios are even fewer. Different teams basically maintain their own business components.

ErpanOmer

Yes, that happens.

ddv

Web components already support server-side rendering.

吉凯

Custom DOM, can it integrate with TypeScript types? Do you have to blindly memorize the parameters to pass?

See top comments, translated →
Source: juejin.cn ↗ Google Translate ↗ Backup ↗