Web Components появились в браузерах в 2011 году — Google предложил стандарт, и все сказали «это будущее». Прошло 15 лет. React захватил рынок, Vue вырос из ниоткуда, Svelte добавил интриги. А Web Components всё ещё «будущее».

Что с ними не так? Или всё-таки так?

Что это вообще такое

Web Components — не библиотека и не фреймворк. Это набор нативных браузерных API, которые позволяют создавать собственные HTML-элементы. Буквально: вы пишете <my-button> и браузер понимает, что с этим делать.

Стандарт держится на трёх китах:

Custom Elements — регистрируете новый тег. customElements.define('my-button', MyButtonClass) — и теперь <my-button> полноценный элемент со своим поведением.

Shadow DOM — изолированное DOM-дерево внутри элемента. CSS снаружи не проникает внутрь, стили компонента не текут наружу. Никакого конфликта классов.

HTML Templates — тег <template>, содержимое которого не рендерится до момента, пока вы его явно не вставите в документ. Удобно для переиспользуемых кусков разметки.

Всё это — часть HTML-спецификации. Без npm, без webpack, без babel.

Почему они не взлетели массово

Если Web Components — нативный стандарт, почему все пишут на React?

Первая причина: время. Custom Elements v1 (нормальная версия) приехала в Chrome в 2016, в Firefox — в 2019. Safari долго упирался. Экосистема React к тому моменту уже работала везде через полифиллы. Пока стандарт согласовывался комитетами, React строил сообщество.

Вторая причина: DX. Написать компонент на чистых Web Components — значит писать больше кода, чем в любом фреймворке. Вот простейший счётчик:

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

  connectedCallback() {
    this.render();
    this.shadowRoot.querySelector('button').addEventListener('click', () => {
      this._count++;
      this.render();
    });
  }

  render() {
    this.shadowRoot.innerHTML = `
      <style>button { color: blue; }</style>
      <p>Count: ${this._count}</p>
      <button>+1</button>
    `;
  }
}

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

В React то же самое — 5 строк. Здесь — 25, и это без нормальной реактивности, без state management, без шаблонизатора. Перерисовывать innerHTML целиком при каждом изменении — варварство.

Третья причина: реактивность нужно делать самому. Web Components не следят за данными. Изменили переменную — DOM сам не обновится. Нужно либо писать свой микро-фреймворк, либо подключать библиотеку.

Где они реально работают

При всём этом Web Components живут, причём в очень серьёзных местах.

GitHub использует их для большей части интерфейса. Теги <relative-time>, <details-dialog>, <include-fragment> — их собственные компоненты, открытый исходный код.

Adobe Spectrum — дизайн-система Adobe — построена целиком на Web Components. Это позволяет использовать компоненты в любом фреймворке: в React, Vue, Angular и в чистом HTML.

Salesforce Lightning — весь UI Salesforce. Миллионы пользователей ежедневно.

YouTube частично перешёл на Polymer — надстройку над Web Components от Google.

Видите закономерность? Это крупные компании с большими командами, которым нужна фреймворк-независимость. Они не могут позволить себе привязаться к React — завтра выйдет React 5 с breaking changes, и переписывать UI на 200 компонентов никто не хочет.

Shadow DOM — главная суперсила

Из трёх API самый интересный — Shadow DOM. Именно он делает компоненты по-настоящему изолированными.

Когда создаёте Shadow DOM, браузер строит отдельное дерево, скрытое от внешнего документа. Стили снаружи туда не попадают. Ваши стили не вытекают наружу. JavaScript-запросы вроде document.querySelector не видят, что внутри.

Это решает боль, знакомую каждому фронтендеру: подключаешь чужой виджет, он ломает вёрстку — потому что использует классы .button, .title, .wrapper, которые пересекаются с вашими.

С Shadow DOM такого не будет. Виджет живёт в своей капсуле.

Обратная сторона: глобальные стили (CSS Variables и часть cascade) всё равно проникают внутрь. Это фича, а не баг — позволяет передавать тему через переменные. Но поначалу кажется нелогичным и сбивает с толку.

Lit — главный инструмент для Web Components

Писать на голых Web Components неудобно. Поэтому Google разработал Lit (раньше Polymer и LitElement).

Lit — минималистичная библиотека (~5 КБ gzip), которая добавляет реактивные свойства, шаблонизатор на tagged template literals и декораторы. Тот же счётчик на Lit:

import { LitElement, html } from 'lit';
import { customElement, property } from 'lit/decorators.js';

@customElement('my-counter')
class MyCounter extends LitElement {
  @property({ type: Number }) count = 0;

  render() {
    return html`
      <p>Count: ${this.count}</p>
      <button @click=${() => this.count++}>+1</button>
    `;
  }
}

Уже нормально. И это компилируется в нативный Web Component — без рантайма React, без Virtual DOM.

Есть и другие инструменты: Stencil (используется Ionic), Haunted (хуки для Web Components), FAST от Microsoft — используется в Fluent UI.

Интеграция с React и Vue

Один из главных аргументов в пользу Web Components — они работают в любом окружении. Но с React исторически был нюанс.

React до версии 19 плохо дружил с Custom Elements. Передать объект или массив через атрибут было неудобно — React конвертировал всё в строки. Обработка кастомных событий тоже отличалась от обычных.

С React 19 это починили: теперь React нормально работает с Custom Elements — передаёт свойства напрямую, слушает кастомные события без обёрток.

Vue и Angular всегда поддерживали Web Components лучше. Angular вообще умеет компилировать свои компоненты в Web Components через @angular/elements — удобно, если нужно переиспользовать что-то вне Angular-проекта.

Когда стоит использовать

Дизайн-системы для больших команд — идеальный кейс. Если у вас несколько продуктов на разных фреймворках, Web Components позволяют один раз написать компонент кнопки, модалки, таблицы и использовать везде без адаптации.

Виджеты для встраивания — чат-боты, формы обратной связи, кнопки отзывов. Клиенту нужно вставить один тег — всё работает без конфликтов со стилями сайта. Именно так в REEXY делают встраиваемые виджеты для клиентов: Shadow DOM гарантирует, что компонент не сломает чужую вёрстку независимо от того, на чём сделан сайт.

Микрофронтенды — когда разные команды пишут разные части одного интерфейса на разных технологиях. Web Components позволяют изолировать части друг от друга.

Долгосрочные проекты — если уверены, что проект живёт 10+ лет, нативный стандарт надёжнее, чем фреймворк. HTML-спецификация обратно совместима; React 5.0 может принести breaking changes.

Когда не стоит

Обычный сайт или лендинг — избыточно. Корпоративный сайт или лендинг — не тот масштаб, при котором выгоды Web Components перекрывают порог вхождения.

Команда не знакома со стандартом — кривая обучения есть. Разработчики, которые всю жизнь писали на React, поначалу будут работать медленнее и совершать неочевидные ошибки с Shadow DOM.

Нужна быстрая разработка — экосистема React богаче на порядок. Готовых компонентов, документации, решений для типичных задач несравнимо больше.

Сложный state management — Zustand, Redux, TanStack Query — у фреймворков куда богаче инструменты для управления состоянием. В мире Web Components это нужно собирать из отдельных библиотек.

Поддержка браузеров в 2026

Custom Elements v1 поддерживают все современные браузеры: Chrome 67+, Firefox 63+, Safari 12.1+, Edge 79+. Полифиллы нужны только для IE11 — но это уже музейный экспонат.

Одна проблема осталась: декларативный Shadow DOM (DSR). Это возможность задать Shadow DOM прямо в HTML без JavaScript — нужно для SSR. Chrome поддерживает, Firefox добавил в версии 123, Safari — в 17.4. Почти полное покрытие, но «почти» — слово, которое всё портит при работе с edge cases на продакшне.

Производительность

Нативные API быстрее, чем библиотеки поверх них — в теории. На практике всё зависит от того, как пишете.

Lit показывает хорошие результаты в бенчмарках: обновление DOM быстрее, чем у React с Virtual DOM, в простых сценариях. Но React с Concurrent Mode умеет делать сложные приложения очень отзывчивыми.

Для виджетов и встраиваемых компонентов — Web Components выигрывают однозначно. Не нужно тащить рантайм React весом 40+ КБ для кнопки с анимацией загрузки.

Стандарт или ниша

Честный ответ: и то, и другое.

Web Components — стандарт в том смысле, что это часть HTML-спецификации. Браузеры поддерживают их нативно, и это не исчезнет. GitHub, Adobe, Salesforce, Microsoft — достаточно серьёзные имена, чтобы технологию не хоронить.

Но это нишевая технология в том смысле, что для большинства задач — обычных сайтов, интернет-магазинов, стартапов — React или Vue дают более быструю разработку, богатую экосистему и больше готовых решений.

Область, где Web Components безусловно выигрывают: интероперабельность. Когда нужно написать один раз и использовать везде — в React-приложении, на WordPress-сайте, в Angular-проекте — альтернативы нет.

Для команды, которая строит дизайн-систему или встраиваемые виджеты, — это первый кандидат на рассмотрение. Для стартапа, которому нужно выкатить MVP за месяц, — React быстрее.

Следите за развитием декларативного Shadow DOM и инструментами вроде Lit. Если DSR получит полную поддержку во всех браузерах, а инструменты продолжат развиваться — Web Components займут гораздо более заметное место в типичном фронтенд-стеке. Пока — это мощный инструмент, который стоит знать и применять там, где он уместен.