Да кто такие эти ваши веб-компоненты?!

Алексей Назаренко, MinskJS #12, 2025.

Да кто такие эти ваши веб-компоненты?!

Алексей Назаренко

Алексей Назаренко.

Веб-компоненты Web Components.

2010 👴

Проект «Паркур» 🧗

Проект «Паркур»

Скриншот записи доклада с Polymer Summit 2017. Алекс Рассел рассказывает о внедрённых в браузеры технологиях в рамках проекта 'паркур'. На слайде перечислен список функций: Custom Element, template, Shadow DOM, HTML Imports, Model Driven Views, Mutation Observer, Subclassable DOM, Classes, Traits & Interfaces, Traceur (transpiler), Deferreds (promises), async/await, Object.observe(), TC39 Stages model, CSS Variables, CSS Mixins, Hierarchal CSS, CSS OM, Shadow Styling, Web Animations, Polyfills. Web Components: Just in the Nick of Time

Первый черновик

Скриншот страницы с черновиком спецификации Introduction to Web Components от 22 марта 2012 года. Introduction to Web Components, W3C Working Draft 22 May 2012

ReactJS

Скриншот записи доклада с JSConf 2013. Джордан Уок презентует React и рассказывает о его технических особенностях. Tom Occhino and Jordan Walke: JS Apps at Facebook

2025 🕰

Веб-компоненты сегодня

Are Web Components A Thing Yet?/

Web Almanac 2024

Скриншот из Web Almanac 2024. На 7.8% страниц используются Custom Elements, 2.5% мобильных страниц используют Shadow DOM, 0.28% мобильных страниц используют template. JavaScript | 2024 | The Web Almanac by HTTP Archive

Chrome Platform Status

Скриншот из Chrome Platform Status. По данным на 1 марта 2025 года 17.7% загружаемых в Chrome страниц регистрируют как минимум один пользовательский элемент. Chrome Platform Status: CustomElementRegistryDefine

Спорная тема 🗯️

Да кто такие эти ваши
веб-компоненты?!

Абстрактный человечик с молотком в руках замахивается, чтобы разбить ноутбук.

Выпуск 443 — Веб-стандарты

Обложка 443 выпуска подкаста 'Веб-стандарты'. На фото: Вадим Макеев, Полина Гуртовая, Алексей Назаренко и Алексей Симоненко. Выпуск 443 — Веб-стандарты

Попробуем разобраться 🕵️‍♂️

Определение

Веб-компоненты — набор API веб-платформы, с помощью которых можно создавать собственные повторно используемые DOM-элементы с изолированной разметкой, стилями и поведением.

Понятнее, конечно же, не стало

Леонид Каневский стоит в дверях на фоне двух разговаривающих мужчин. Ниже надпись 'Понятнее, конечно же, не стало'.

Определение

Веб-компоненты — набор API веб-платформы, с помощью которых можно создавать собственные повторно используемые DOM-элементы с изолированной разметкой, стилями и поведением.

API веб-платформы ⚙️

API веб-платформы

Зонтичный термин ☂️

Custom Elements

class QuantityInput extends HTMLElement { constructor() {} // Элемент создан connectedCallback() {} // Элемент добавлен в DOM disconnectedCallback() {} // Элемент удалён из DOM adoptedCallback() {} // Элемент перенесён из другого документа static observedAttributes = [] // Наблюдаемые атрибуты attributeChangedCallback(name, oldVal, newVal) {} // Изменился наблюдаемый атрибут } customElements.define('quantity-input', QuantityInput); // регистрация

Custom Elements

class QuantityInput extends HTMLElement { static formAssociated = true; // Элемент должен ассоциироваться с формой connectedCallback() { // Возможность работы с формами, валидацией, пользовательскими состояниями и ARIA this._internals = this.attachInternals(); } formAssociatedCallback(form) {} // Элемент ассоциирован с формой formDisabledCallback(disabled) {} // Форма отключена formResetCallback() {} // Форма сброшена formStateRestoreCallback(state, mode) // Форма восстановлена или сработал autocomplete } customElements.define('quantity-input', QuantityInput); // регистрация

Templates

<template id="quantity-input"> <div class="base"> <label for="input"></label> <button type="button" id="inc"> + </button> <button type="button" id="dec"> - </button> <input type="number" id="input"> </div> </template> const t = document.createElement('template'); t.innerHTML = ` <div class="base"> <label for="input"></label> <button type="button" id="inc"> + </button> <button type="button" id="dec"> - </button> <input type="number" id="input"> </div> `;

Templates

class QuantityInput extends HTMLElement { connectedCallback() { // Находим template const t = document.querySelector('#quantity-input'); // Клонируем шаблон this.innerHTML = t.content.cloneNode('true'); } } customElements.define('quantity-input', QuantityInput);

Shadow DOM

class QuantityInput extends HTMLElement { connectedCallback() { // Находим template const t = document.querySelector('#quantity-input'); // Добавляем Shadow DOM this.attachShadow({ mode: 'open' }); // Клонируем шаблон this.shadowRoot.innerHTML = t.content.cloneNode('true'); } } customElements.define('quantity-input', QuantityInput);

Определение

Веб-компоненты — набор API веб-платформы, с помощью которых можно создавать собственные повторно используемые DOM-элементы с изолированной разметкой, стилями и поведением.

Повторное использование ♻️

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

class QuantityInput extends HTMLElement { /* ... */ } customElements.define('quantity-input', QuantityInput); <head> <!-- ... --> <script src="quantity-input.js"></script> </head> <body> <quantity-input label="Количество" value="1"></quantity-input> <!-- ... --> <quantity-input label="Количество" value="5"></quantity-input> </body>

Разные источники и компоненты

<quantity-input value="1"></quantity-input> <calendar-date> <calendar-month></calendar-month> </calendar-date> <sl-select label="Тема"> <sl-option value="dark">Тёмная</sl-option> <sl-option value="light">Светлая</sl-option> <sl-option value="system">Системная</sl-option> </sl-select>
➡️
JavaScript.
app.js

Определение

Веб-компоненты — набор API веб-платформы, с помощью которых можно создавать собственные повторно используемые DOM-элементы с изолированной разметкой, стилями и поведением.

Инкапсуляция 🚧

Shadow DOM

<quantity-input label="Количество" value="1"></quantity-input> <quantity-input label="Количество" value="1"> #shadow-root (open) <div class="base"> <label for="input">Количество</label> <button type="button" id="inc">+</button> <button type="button" id="dec">-</button> <input type="number" id="input" value="1"> </div> </quantity-input>

What We Do In The Shadow (DOM)

Скриншот записи доклада с MinskCSS 12. Алексей Назаренко объясняет что такое Shadow DOM. На слайде с заголовком 'Что такое Shadow DOM' список из трёх пунктов: Браузерный API, Часть веб-компонентов, Обещает инкапсуляцию. What We Do In The Shadow (DOM)

Примитивы 🔩

An Attempted Taxonomy of Web Components

Обложка статьи 'An Attempted Taxonomy of Web Components' Зака Лезермана. На фоне много раскрытых книг, поверх которых название статьи, фото Зака, zachleat.com, №392, November 18, 2023. An Attempted Taxonomy of Web Components

Комбинации примитивов

Я *должен* добавить, что это замечательно, что люди дали имена полезным подкомбинациям этих примитивов. Мы не стали их называть, но предвидели, что некоторые пользователи будут игнорировать, например, <template> или CE [Custom Elements] или SD [Shadow DOM] и просто будут использовать другие части. С моей точки зрения, это прекрасно и работает как задумано.

— Alex Russel
Bluesky — Alex Russell

Веб-компоненты
↕️
Пользовательские элементы

Два значения

Веб-компоненты

👇

Набор API: Custom Elements,
Templates, Shadow DOM, ...

Веб-компоненты
🆚
Фреймворки

Веб-компоненты и фреймворки

Веб-компоненты Фреймворки
Низкоуровневые примитивы Высокоуровневые абстракции
Встроены в браузеры Сторонняя зависимость
Работают как есть Требуется сборка
Базовые возможности Продвинутые возможности
Плохой DX Хороший DX

Вы не понимаете, это другое

Отказаться от зависимостей и не умереть

Отказаться от зависимостей и не умереть

Совместимость 🖇️

Веб-компоненты в классическом SSR

Web Components. ➡️
Ruby On Rails. WordPress. Laravel. Django.

Острова 🏝

Веб-компоненты в SPA-фреймворках

Web Components. ➡️
React. Vue. Angular. Svelte.

Custom Elements Everywhere 🍻

Специфичный UI-Kit

MUI. 🤝 React.
Vuetify. 🤝 Vue.
Angular Material. 🤝 Angular.

Специфичный UI-Kit

MUI. 🤝 React.
MUI. 🫷 Vue.
MUI. 🫷 Angular.

Vendor lock 🔒

Универсальный UI-Kit

Web Components. 🤝 React.
Web Components. 🤝 Vue.
Web Components. 🤝 Angular.

Using Web Components to Scale Your UX

Скриншот записи доклада с конференции Stir Trek 2024. Бартон Смит из Microsoft рассказывает об устройстве Microsoft Partner Center. На слайде схема в виде пяти столбцов, которые иллюстрируют рпзличные используемые технологии: ASP DOT NET, React, Vue, Angular и Web Components. Каждый столбец пересекает строка с надписью Harmony Component Library, что иллюстрирует совместимость библиотеки компонентов с каждой используемой технологией. Using Web Components to Scale Your UX

Веб-компоненты из SPA-фреймворков

React. Vue. Angular. Svelte.
➡️ Web Components.

Совместимость

JavaScript. ➡️ Web Components. ➡️ Angular.
Angular. ➡️ Web Components. ➡️ React.
React. ➡️ Web Components. ➡️ Vue.

Библиотеки компонентов 📚

Библиотеки компонентов

Open WC: Component Libraries

Photoshop Web

Приложение создается несколькими командами с использованием различных инструментов и подходов, но его разрозненные части должны быть объединены в единое целое с сохранением высокой производительности.

Чтобы решить эту задачу, Adobe обратилась к веб-компонентам и библиотеке Lit. Элементы интерфейса Photoshop созданы на основе библиотеки Spectrum Web Components [...], которая работает с любым фреймворком или без него.

— Photoshop’s journey to the web
Photoshop’s journey to the web

Innovations with FAST Web Components

Скриншот записи доклада с Reliable Web Summit 2021. Роберт Эйзенберг рассказывает про инструмент FAST для работы с веб-компонентами. На слайде с заголовком 'Web Component Performance' графики сравнения страницы на React и на веб-компонентах. На десктопе в Google Chrome веб-компоненты дают семикратное уменьшение времени на выполнение скрипта по сравнению с React. На мобильном устройстве Moto G4 в Chrome веб-компоненты дают шестикратное уменьшение времени на выполнение скрипта. Innovations with FAST Web Components

Улучшения отзывчивости в Edge

В Edge 122 интерфейс Browser Essentials стал более отзывчивым. Интерфейс стал на 42% быстрее для пользователей Edge и на 76% быстрее для тех, кто работает на устройствах без SSD или у кого менее 8 ГБ ОЗУ!

Избранное — еще одна функция, которая получила улучшения отзывчивости интерфейса в Edge 124. Независимо от того, развернуто или свернуто избранное, работа с ним должна стать на 40% быстрее.

— An even faster Microsoft Edge
An even faster Microsoft Edge

Инструменты 🧰

Инструменты

Lit.
Lit
Stencil.
Stencil
FAST.
FAST
Catalyst.
Catalyst
Lion.
Lion
The only online IDE for Web Components

Lit vs React

import { LitElement, html } from 'lit'; import { customElement, property } from 'lit/decorators.js'; @customElement('app-counter') class Counter extends LitElement { @property() count = 0; increment() { this.count += 1; } render() { return html` <button @click="${this.increment}"> ${this.count} </button> `; } } import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); const increment = () => { setCount(count + 1); }; return ( <button onClick={increment}> {count} </button> ); }

Шило на мыло 🧼

Преимущества веб-компонентов

Недостатки веб-компонентов

Веб-компоненты:

Спасибо за внимание!

Слайды: wtf-web-components-minskjs.netlify.app
Канал: <divelopers>
Telegram: @alexnozer

Алексей Назаренко