Создаём масштабируемые дизайн-системы на Progressive Web Components
Прогрессивные Web Components: как строить системы дизайна на годы вперед
Если вы создавали библиотеки компонентов для крупных проектов, то знаете эту проблему. Web components дают настоящую свободу — работают везде, без привязки к фреймворкам. Но на деле их портят: сдвиги верстки до загрузки JS, проблемы с доступностью из-за Shadow DOM и головная боль с серверным рендерингом.
Парадокс в том, что мы сами всё усложняем.
Парадокс Web Components
Обычно так: команда берётся за design system на web components. Делают Custom Elements, подключают тяжёлый фреймворк — и вот уже кнопка жрёт килобайты JS. HTML приходит пустым, JS перерисовывает всё заново. Пользователь видит мигание без стилей. Скрипт-ридеры путаются в Shadow DOM. SSR превращается в кошмар.
Виноваты не web components. Виновато, как мы их строим.
А что если начать с простого?
Лучшие идеи кажутся очевидными потом. Представьте: компоненты сначала — чистый HTML и CSS. JS не база, а надстройка.
Это суть Progressive Web Components — подход к архитектуре (не фреймворк). Два слоя:
Базовый слой — HTML и CSS. Рендерится сразу, без JS. Контент виден, стили на месте, страница не прыгает.
Слой улучшений — JS для интерактива, событий и реактивности. Только когда надо.
Три типа компонентов
Не все компоненты одинаковы. Progressive Web Components делятся на три вида:
Композитные оборачивают готовый HTML. Дропдаун на <select>, табы на списках. Light DOM даёт доступность и совместимость с фреймворками из коробки.
Примитивные — самодостаточные. Датапикер, слайдер, календарь. Базовый HTML показывается сразу, JS добавляет магию.
С Declarative Shadow DOM — с нативным Shadow DOM и поддержкой SSR. Идеально для изоляции стилей без серверных танцев.
Выбирайте под задачу. Нет жёстких правил — только принцип слоёв.
Практика на деле
Идея ясна, но как воплотить в десятках компонентов? Тут важны детали.
Библиотека должна решать:
- Синхронизацию пропсов и атрибутов между фреймворками
- Делегирование событий без Shadow DOM
- Гидратацию без лишней перерисовки
- Scoped CSS без JS-нагрузки
- Доступность с нуля
- SSR без серверных хаков
Большинство библиотек web components заставляют всё это писать вручную. "Прогрессивность" теряется, JS становится обязательным.
Новая архитектура компонентов
Правильный подход меняет приоритеты:
Сначала HTML. Начальное состояние — семантичный HTML, который работает сам. Стилизуйте CSS, обеспечьте доступность. JS — только для интерактива.
JS опционален. Форма с валидацией живёт без JS. Меню доступно в базовом HTML. Улучшения — не необходимость.
Используйте платформу. Custom Elements, Shadow DOM (по делу), Slots, Declarative Shadow DOM — всё родное.
Поддержка фреймворков. HTML-основа работает в React, Vue, Angular, Svelte или ванильном JS. Без адаптеров.
SSR по умолчанию. HTML и CSS рендерятся на сервере легко. Для реактивности — гидратация на клиенте.
Размер имеет значение
Сколько JS нужно библиотеке компонентов?
Обычные — 50 КБ+. Progressive Web Components — в разы легче. HTML/CSS сначала, JS сверху: весь оверхед — 2,6 КБ. Остальное — ваши компоненты.
Это решает производительность. Быстрее скачивание, парсинг, выполнение. На мобильном интернете — разница в 3 секунды против 8.
SSR без боли
Обычно SSR требует серверной магии. Progressive Web Components меняют правила: HTML/CSS рендерятся сами.
Композитные и Declarative — без доработок. С реактивностью — базовый HTML на сервере, интерактив на клиенте.
Web components перестают быть проблемой для SSR-приложений.
Библиотеки, которые не устареют
Для design system Progressive Web Components дают редкое: переносимость без потерь.
Нет зависимости от React-бандла или Vue-экосистемы. Компоненты живы в сегодняшнем фреймворке и в том, что будет через три года.
Нужна дисциплина: меньше JS, больше семантики HTML, умный CSS. Зато результат — переиспользуемые, быстрые, доступные компоненты.
Итог
Web components не провалились. Мы просто строили их как JS-фреймворки, а они — HTML-элементы. Progressive Web Components возвращают к основам: платформа веб, слои по делу, итог — лёгкие, переносимые, performant.
Для больших design systems это killer-фича.