跪拜 Guibai
← Back to the summary

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

Why Can't Web Components Catch Fire?

Hearing Web Components, it seems like a very high-end technology 🤔.

It is the brainchild of W3C, a browser-native component standard composed of three underlying APIs: Custom Elements, Shadow DOM, and HTML Templates. It has been a full 13 years since Google first proposed the concept in 2013.

Logically, a component standard with native browser support, no dependency on third-party frameworks, and natural cross-framework reusability should have dominated the front-end world long ago 🤷‍♂️.

But the reality is: the vast majority of front-end engineers are still using React or Vue to write components, and the adoption rate of Web Components in actual commercial projects is embarrassingly low.

Why? Because technical correctness has never been equal to engineering usability. Let's talk about it 👇.


A Cliff-like Lag in Developer Experience

The biggest enemy of Web Components is not React, but its own extremely primitive developer experience.

Let's look directly at the same requirement—a clickable counter component—and compare the code under the two systems:

The React way:

function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(c => c + 1)}>Clicked {count} times</button>;
}

Just 3 lines of code, clear logic, state-driven views, any junior front-end developer can understand it instantly 🙌.

The native Web Components way:

class MyCounter extends HTMLElement {
  constructor() {
    super();
    this._count = 0;
    this._shadow = this.attachShadow({ mode: 'open' });
    this._render();
  }

  _render() {
    this._shadow.innerHTML = `
      <style>
        button { padding: 8px 16px; cursor: pointer; }
      </style>
      <button>Clicked ${this._count} times</button>
    `;
    // After each re-render, events must be manually rebound because innerHTML destroys old DOM nodes
    this._shadow.querySelector('button').addEventListener('click', () => {
      this._count++;
      this._render(); // Manually trigger re-render, no automated reactive mechanism
    });
  }
}

customElements.define('my-counter', MyCounter);

For the same functionality, native Web Components requires more than 5 times the code of React. And it is filled with extremely primitive manual operations: manually concatenating HTML strings, manually binding events, manually triggering re-renders, manually managing state.

This is not writing modern components; this is using 2026 browser APIs to write 2010-style jQuery code 😖.


No Built-in Reactivity System

React has useState, Vue has ref and reactive, and their core selling point is state-driven views: you just change the data, and the framework automatically updates the DOM for you.

But the Web Components standard has no built-in reactivity mechanism.

ChatGPT Image 2026年8月25日 14_02_30.png

You modify an attribute, and the DOM does not update automatically. You must implement attributeChangedCallback yourself, manually find the corresponding DOM node, and manually change its textContent. When the component's state becomes complex (like a form with 20 linked fields), the manual synchronization logic you need to write will spread like weeds, eventually turning into an unmaintainable plate of spaghetti.

Some people say: You can use 👉 Lit, it adds reactivity to Web Components.

That's right, Lit does greatly improve the development experience. But the question is: When you must rely on a third-party library to make a native standard usable, what is the point of that native standard 🤷‍♂️? Writing Web Components with Lit and writing components with React are essentially both depending on a framework. It's just that React's ecosystem is hundreds of times larger than Lit's.


The Style Isolation of Shadow DOM

Shadow DOM is the proudest feature of Web Components: it provides true style isolation, where the component's internal CSS does not leak out, and external CSS cannot intrude in.

This is theoretically beautiful. But in real business development, this absolute isolation quickly becomes a destabilizing factor.

ChatGPT Image 2026年8月25日 15_37_12.png

When your designer says all buttons across the site should use brand blue, you find you simply cannot use a global CSS variable to penetrate the boundary of Shadow DOM (although CSS Custom Properties can penetrate, this requires the component's internal code to actively cooperate by exposing interfaces, which many third-party Web Components have not done).

When you want to use Tailwind CSS utility classes to quickly adjust a component's styles, you find these classes are completely ineffective inside Shadow DOM, because the stylesheet generated by Tailwind cannot be injected into the Shadow Root at all 😖.

Isolation is good, but uncontrollable isolation is a disaster. React and Vue components do not have Shadow DOM, but through CSS Modules, Scoped CSS, or Tailwind, they can achieve good enough style isolation while retaining the flexibility of global theme overrides.


No SSR Support

In 2026, Server-Side Rendering (SSR) has transformed from an optional solution to a project standard. React has Next.js, Vue has Nuxt, and their SSR ecosystems are extremely mature.

ChatGPT Image 2026年8月25日 15_51_52.png

But Web Components' SSR support remains an extremely awkward semi-finished product to this day.

Custom Elements fundamentally rely on the browser's JavaScript engine for registration and execution. In the server-side Node.js environment, the customElements.define API simply does not exist. This means your Web Components can only output an empty shell tag on the server (like <my-counter></my-counter>), and all content must wait for the client-side JavaScript to load and execute before rendering.

For a commercial project that values SEO and first-screen performance, this is an unacceptable fatal flaw 🤔.


Cross-Framework Reuse is a Pseudo-Requirement

The biggest marketing point of Web Components is: Write once, reuse in any framework.

This sounds extremely tempting. But think about it calmly: in a real project, how many projects does your team have that mix React and Vue simultaneously?

The answer is almost zero; the use case is very rare.

The vast majority of companies have a unified front-end tech stack. Once React is chosen, all projects use React; once Vue is chosen, all projects use Vue. In a team with a single tech stack, cross-framework reuse is a non-existent requirement. To satisfy a pseudo-requirement, you endure the terribly poor developer experience of Web Components—this trade-off simply doesn't add up 🫵.


So Where Is It Actually Suitable?

Having mentioned so many flaws, is Web Components completely worthless? Not exactly 🖐️.

In one very specific scenario, it remains the irreplaceable optimal solution: cross-team foundational design systems in large enterprises.

ChatGPT Image 2026年8月25日 16_00_16.png

When a company has dozens of front-end teams, using React, Vue, and even Angular respectively, writing the underlying base UI components (buttons, input boxes, dialogs) in a specific framework will inevitably exclude teams using other frameworks. At this point, using Web Components to build a framework-agnostic foundational design system is the only solution that allows all teams to integrate painlessly.

GitHub's Primer, Adobe's Spectrum, SAP's UI5—the design systems of these top-tier enterprises have all chosen Web Components at their base.

But please note, this is a problem only a very small number of large enterprises encounter. For 99% of small and medium-sized teams, directly using a React or Vue component library is always the most cost-effective choice 😀.


Some Thoughts 🤔

The outcome of Web Components illustrates one thing to all technologists.

Whether a technical solution succeeds never depends on how correct it is at the standard level. The endorsement of W3C, native browser support, theoretically perfect architecture—these things all pale into insignificance when faced with daily development.

Developers vote with their feet. Whose development experience is good, whose ecosystem is strong, who can help me deliver requirements before the deadline, that's who I'll use 🖐️.

React and Vue won, not because they are more correct than Web Components, but because they are easier to use and more flexible!

Do you agree 😀?


If you like my articles, feel free to follow my WeChat Official Account: 【前端技术官】.

Mainly sharing: Front-end Architecture · AI Programming · Workplace Cognition · Developer Growth

前端技术官-ErpanOmer

Scan the WeChat code to follow 👆

Updates are irregular, no spam, just chatting about truly useful stuff.

Comments

Top 1 of 2 from juejin.cn, machine-translated. The original thread is authoritative.

贾东雷

Big companies are also pseudo-requirements. It's simply impossible for different teams to use the same component library. The communication cost is too high. Take Ant Design as an example. It's supposed to be usable across different teams, right? It's completely useless. If it's business components, the scenarios are even fewer. Different teams basically maintain their own business components.

ErpanOmer

Yes, that situation does happen.