Comments 44
По своему опыту, могу добавить, что веб-компоненты прекрасно интегрируются с классическими фреймворками (проверял на React и Vue, не обязательно переписывать всё приложение сразу на веб-компоненты, период со смешением технологий переносится прекрасно), довольно удобно стилизуются через нативные css-переменные, вместо шаблонов я бы предпочёл создавать их через createElement и appendChild (это производительнее и гибче), очень хорошо переиспользуются, в том числе в продуктах, написанных на разном технологическом стеке. Из минусов: пока не нашёл хорошего способа делать unit-тесты, пока нет поддержки в IE/Edge, всё ещё нужен способ делать дата-биндинг, так как нативной технологии для этого пока нет. Но в целом впечатления только позитивные, начинаем потихоньку использовать во внутренних админках, не требующих IE.
rboots — Edge, который Microsoft Edge на Chromium справляется со всеми фишками не хуже хрома. и даже опережает лису.
Странно, что автор называет изолированные стили чуть ли не основным недостатком. По мне, так это огромное достоинство: в вашей дизайн-системе должно быть четкое API и ничего более удобного и эффективного, чем CSS Custom Properties для реализации данной задачи я не встречал. Все работает четко: без протечек, сайд-эффектов и монструозных определений в стиле БЭМ. Делать поддержку тем и прочих кастомизаций — одно удовольствие.
Это зависит исключительно от того, что вы понимаете под «темой». Цвета навесить или отступы покрутить — да, на переменных еще как-то нормально, но зависит от числа компонентов. На дюжине нормально, на полсотне — задолбаетесь. UI Kit от приложения навесить на ваши компоненты? Уже всё становится очень грустно. Кастомизация в широком смысле, когда компонент — это что-то очень общее, типа ресайзающегося (с блекджеком и женщинами легкого поведения) модального окошка? Удачи сидеть и добавлять переменные.

Когда ваши компоненты или не подлежат какой-то особой кастомизации, или подлежат, но количество контекстов очень маленькое — тогда с переменными работать можно, и теневой DOM даже в некотором смысле удобен. Но это не масштабируется совсем, и комбинаторный взрыв поджидает буквально за углом. Без ::part лично я бы не рискнул связываться с теневым DOM, если только у меня не будет полного контроля за контекстом использования моих компонентов; это имеет огромные шансы в будущем выродиться в десятки часов пустопорожней работы вида «а добавь нам переменную вот сюда».

PS: Кстати, касательно протечек — у переменных общий неймспейс, и если вы на второй сотне переменных добавите такую, имя которой уже где-то было, то немедленно получите те самые протечки ^_^
Я, какбэ, по долгу службы, специализируюсь именно на UI-либах и дизайн-системах. И вот я читаю, что вы пишите — и вообще не понимаю о чем вы. Ни разу не пришлось задолбаться за несколько лет плотного использования компонентов с Shadow DOM. Возможно, в ваших проектах имеются какие-то существенные проблемы с декомпозицией, поскольку если у вас имеется базовый набор примитивов (а их никак не может быть полсотни) с поддержкой своих свойств и более общие компоненты, состряпанные из данных примитивов — никакого комбинаторного взрыва там быть не может. Делаете вы модальное окошко? Ок, его собственное поведение инкапсулировано в нем самом, а для скрытия используется стандартная библиотечная кнопка с тем-же компактным набором общих свойств, что и остальные примитивы… Свойства могут быть ПЕРЕопределены для каждой ветви DOM-дерева, поэтому для разных случаев, в рамках одного документа, в примитивах используются все равно один и тот-же компактный набор свойств. Не вижу тут никакой фундаментальной системной проблемы, хотя конечно, ее можно создать, если специально постараться.
Я, какбэ, по долгу службы, специализируюсь именно на UI-либах и дизайн-системах. И вот я читаю, что вы пишите — и вообще не понимаю о чем вы.

Серьезно? Вы специализируетесь на UI-либах и дизайн-системах, и вам никто ни разу не говорил «вот у нас бутстрап, а у вас ваша либа, нам надо, чтоб бутстрап был натянут на ваши компоненты»?
Вы специализируетесь, но не понимаете, в чём тут беда, когда у вас на какую-нибудь кнопочку заведено 12 переменных (это я пересчитал, сколько стилей кнопочек у нас в проде перекрывается)? И что это нужно умножить на количество простых компонентов (которых, в самом деле, 50 не будет, но 20 — вполне)? И что потом для составного компонента из 5 простых задача на кастомизацию будет звучать как «выставите нужные значения для 12 * 5 переменных»? Вы такой css называете «без монструозных конструкций»? Я вам тут сразу скажу, что БЭМ, который никто не любит, и я тоже — в сравнении с портянками из переменных будет менее монструозным, а не наоборот.
А похоже что я шучу? Вы неправильно считаете: не по 12 переменных на кнопочку, а 12 переменных на всю вашу кухню должно хватить. Если у вас в КАЖДОМ примитиве разные переменные для отступов, скруглений, цветов, шрифтов и т.д. — поздравляю, у вас нет вообще никакой дизайн-системы, а есть невнятное легаси-днище которому уже ничто не поможет.
Вы неправильно считаете: не по 12 переменных на кнопочку, а 12 переменных на всю вашу кухню должно хватить.

Эм, нет. По 12 переменных на каждый отдельный контекст, в котором кнопочка должна выглядеть по-своему. И по примерно 12*5 на, к примеру, особо выглядящее модальное окно (предположим, что product owner хочет совсем особо выглядящие модалки на ошибки, ворнинги, уведомления, итд).

То есть, разумеется, не по 12 новых переменных, а по 12 присваиваний значений. И этими портянками будет забит весь css.

Если у вас в КАЖДОМ примитиве разные переменные для отступов, скруглений, цветов, шрифтов и т.д.

«Ваш дизайн говно, вы ничего не понимаете в дизайне» (с) один очень хайповый дизайнер.

Наличие разных переменных в каждом примитиве — не означает, что в конечном дизайне сайта в каждом примитиве будет выставлен свой шрифт, отступы, и т.д. Это всего лишь означает возможность выставить свой шрифт и отступы в тех 2% случаев, которые таки на весь проект обязательно где-то найдутся. Потому что если отдельных переменных нет, и всё закрыто на замок теневого DOM — всё, с этим без дообъявления переменных вы таки ничего не сделаете.
Вы, похоже, не читаете что я пишу. ОДНА переменная может наследовать свое значение из контекста, и иметь РАЗНЫЕ значения для РАЗНЫХ контекстов в рамках вашего приложения, как и в рамках ОДНОГО текущего состояния документа.
А вы, похоже, так и не понимаете, для чего я вообще начал этот разговор. В пределе, модульность компонентов не совпадает с модульностью CSS на переменных и теневом DOM. И чем больший у вас объем работ и чем меньший сектор в итоговом продукте, тем больше шансов словить такой случай и потом подставлять под обрушившуюся модульность костыли.

На конкретном примере это выглядит примерно так:
1) Вы запилили вашу крутую либу примитивов;
2) На этих примитивах запиливаются составные компоненты. Допустим даже это делаете вы сами, и вы всё сделали максимально удобно для переменных. Например, памятуя о том, что кнопки в модалке могут потребоваться самой разной стилизации, вы не запаковали их в составной компонент и пишете примерно так:
<modal>
  <div slot="buttons"><ваши кнопки></div>
</modal>

3) А затем кто-нибудь на стороне продукта говорит: слушай, я не хочу это всё каждый раз писать. У меня есть модалка для ошибок и модалка для всего остального, и ничего другого нет и не будет. Давайте вы для конкретно нас сделаете:
<modal-error></modal-error>
<modal-generic></modal-generic>

Круто, правда? Ну окей, конкретно для них вы взяли и сделали.

А потом на следующий день вам пишет продуктовый дизайнер: «слушай, у нас вот тут модальные диалоги на вашей либе, и мне вот прям страсть как нужно поменять в модальном диалоге для ошибки шрифт на кнопке ОК. Я тут пытаюсь поменять через переменную, но у меня шрифт меняется сразу на всех кнопках этой модалки, а мне это не надо!».

И вот примерно на этом месте к вам плавно придёт осознание того, что компоненты у вас разбиты одним образом, а вот стили — совершенно другим, и чтоб всё работало, вам надо сидеть и сводить одно с другим. Бонус — если компоненты из вашей либы собраны в комплексные компоненты не один раз, а несколько, и на каждом шаге более специализированную либу собирали разные люди.
Круто, правда?

Нет, не круто. Нужно так:
<my-modal error></my-modal>

Ну блин, серьезно, я даже не знаю как такое прокомментировать… Стрелять себе в ногу — это особое искусство.
Для приведенного примера — неважно. Что так, что эдак — обернув , вы лишились возможности подставить значение переменной только для одной его кнопки, и ради такой возможности вам нужно новую переменную, значение которой вы в обертке пробросите до нужного места и передадите в общую переменную для, например, шрифта на кнопочках, но только над одной кнопкой.
То есть, разумеется, не по 12 новых переменных, а по 12 присваиваний значений.

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

Очень смешно.

это уже ничем практически не отличается от стилизации классическими методами

Ну уж нет. Если вы пишете в блокноте — да, разницы мало. Если вы пишете в нормальной среде, то на стилизацию классическими методами у вас будет какая-то проверка синтаксиса, а на переменные не будет ничего. Да и потом в браузере — на каждый случай «не работает» вам придётся посмотреть, не ошиблись ли вы в названии переменной и не запутались ли в именах (и не, например, передаете какое-то неожиданное значение в стиль).
Очень смешно.

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

Конкретно я юзаю VS Code чаще всего. Как-то не заметил особых проблем. Однако, тут вы поднимаете другую проблему, о которой изначально не говорили. Да, очепятки, наверное, возможны, как и в практически в любых других селекторах.
Да, очепятки, наверное, возможны, как и в практически в любых других селекторах.

Опечатки в селекторах возможны с «классикой» и с «переменными», но с переменными помимо этого еще будут опечатки в самих переменных — т.к. никакой проверки существования имени и валидности значений для них нет.
Я, какбэ, по долгу службы, специализируюсь именно на UI-либах и дизайн-системах.

Поэтому с упомянутой проблемой вы и не сталкиваетесь. С ней сталкиваются пользователи ваших UI-либ и дизайн-систем.

PS: Кстати, касательно протечек — у переменных общий неймспейс, и если вы на второй сотне переменных добавите такую, имя которой уже где-то было, то немедленно получите те самые протечки ^_^

Это не так. Точнее тут не совсем применимо слово «неймспейс», в CSS — каскады. И, как я уже написал, одна и та-же переменная может принимать разные значения в разных контекстах, заданных родителем элемента. Но сам набор этих общих переменных — конечно должен быть стандартизирован в рамках проекта.
UFO landed and left these words here
Никогда руки не доходили до PWA, но неужели всё настолько плохо, когда у них аж на заглавной странице вывешено lightning fast to load?
В литах тормозить точно нечему, насчёт всего остального, что там еще в обвязке — не знаю.
UFO landed and left these words here
Они там используют свой собственный резолвер для модулей вместо нативного, плюс грузят непомерную кучу зависимостей. По мне так это извращение какое-то. Так что PWA Starter Kit — не показатель.
UFO landed and left these words here
Я б с радостью, но только когда смогу его читать без боли в глазах. Пока — не выходит. Вот этот вот синтаксис с <= — это не для людей, а для больших человекообразных роботов.
UFO landed and left these words here
Да на самом деле делить и сейчас можно практически везде. По крайней мере чисто формально, по файлам — так-то понятно, что если у тебя шаблонизация, то верстка от кода начисто отделена не будет, биндить-то как-то надо. Но вот чтоб в отдельный файл положить — с этим никаких проблем обычно.

И с вью и стейтом так же. Другое дело, что тысячи всяких туториалов и прочих «давайте сделаем to do list» мешают всё в кучу, а потом народ это всё читает, и пишет так же на проде.
UFO landed and left these words here
ООП учило, что компонент должен быть самодостаточным и живучим — и данными своими управлять, и уметь себя презентовать разными способами, то есть инкапсулировать в себе самом модель и вью.

Смотря что вы хотите получить на выходе. Концептуально нет никаких проблем собрать максимально заточенный под конкретный случай компонент. Это вот то самое банальное, что вы уже скорее всего не раз видели:
<html>
  <body>
    <my-app></my-app>
  </body>
</html>

Всё максимально самодостаточно. Может копать, а может не копать. То есть, работать или не работать.

Но тут внезапно к вам приходит второй клиент, допустим Вася, и говорит, что то, что вы сделали — это круто и здорово, только вот ему от этого нужно вот это, это, и еще вот то. А всё остальное — не нужно, но нужно новое, специально для Васи. Вы, конечно, можете почесать в голове, и воспользоваться сильнейшими средствами разработки под названием ctrl+c, ctrl+v, и через некоторое время сделать <vasya-app>. Потом вы обнаружите, что правки, которые вы делаете в одном месте относительно функционала, который есть и у Васи — вам нужно копировать в два места. Потом к вам придут еще Петя и Вова, и у вас скорее всего начнёт появляться мысль о том, что самодостаточность компонента не может быть самоцелью.

Ну и вообще говоря, SOLID не зря придумали и даже иногда на собеседованиях спрашивают. И ООП всё ж таки не учит тому, что нужно всё-всё в компонент заворачивать. ООП позволяет так сделать, но вот «можно» и «нужно» — это две большие разницы.

PS: А если вернуться к интерфейсам, то «как нужно» вам подскажут все эти MVC, MVP, и MVVM. Это практически один и тот же паттерн, повторяемый немного на разные лады (меньше чистоты — меньше бойлерплейта и наоборот). Лучше этого для дела проектирования интерфейсов до сих пор никто ничего в общем-то и не придумал.

Самодостаточность и нерасширяемость — тоже две большие разницы. Например, все компоненты в $mol самодостаточные и могут использоваться именно, как вы описали:


<html>
  <body mol_view_root="$mol_check_box">
    <!-- ага, тут будет работающий чекбокс -->
  </body>
</html>

Но при этом вы всегда можете настроить его под конкретный контекст использования:


$my_app $mol_view sub /
    <= Toggle_lights $mol_check_box
        title \lights
        checked?val <=> lights_enabled?val true
Самодостаточность и нерасширяемость — тоже две большие разницы.

Это вообще ортогонально моему комментарию выше. Я пишу про то, что в общем виде на вопросы «насколько самодостаточно» и «насколько расширяемо» ответ возможен только один — «насколько вам в рамках вашей задачи нужно».

А я про то, что одно вообще никак не исключает другое и даже можно получить обе характеристики максимальными по умолчанию.

Очевидно нет, нельзя. Чекбокс нельзя (без извращений) расширить до tri-state чекбокса. Чекбокс, который же будет расширяться до tri-state — например, полным выносом логики управления состояниями наружу из чекбокса — уже будет менее самостоятельным, поскольку будет нуждаться в этом самом модуле логики, дефолтном или трехпозиционном.

Совмещать самостоятельность с расширяемостью до некоторой степени можно, а вот максимизировать и то, и другое — не очень.

Я считаю, что в идеале в парадигме UI компонент, как минимум, должен быть трансформер, избирательно кастомизируемый и создаваемый под нужные цели снизу вверх. Исключения могут составлять инпуты и текстфилды. Возможно чекбоксы.
Хотя каких только чекбоксов не делал на флеше:)))

Так это не расширение. Это другой компонент с перекрытой логикой базового компонента. У него, например, насколько я вижу, нет собственного стейта, и без других чекбоксов оно просто работать не сможет — хотя вообще-то нет никакой причины, почему трехпозиционный чекбокс не может быть сам по себе (скажем, в роли переключателя true / false / not set).

От чекбокса ожидаешь, что он будет переключать стейт по клику и уметь в get/set, а у вас group определенную (и нужную) задачу конечно же решает, но гораздо более конкретную.
Это другой компонент с перекрытой логикой базового компонента

Это и называется расширение.


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

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


хотя вообще-то нет никакой причины, почему трехпозиционный чекбокс не может быть сам по себе (скажем, в роли переключателя true / false / not set)

Нет никакой причины использовать такой псевдочекбокс вместо собственно переключателя, который проще и понятней в использовании.

Это и называется расширение.

Расширением это будет, если старый контракт никуда не пропадёт.
UFO landed and left these words here
Only those users with full accounts are able to leave comments. Log in, please.