Pull to refresh

Comments 334

Уж если взялся писать — то надо писать всё, а не часть, и на основании этой части делать вывыды. Где упоминание о template, connectedCallback, disconnectedCallback, adoptedCallback, attributeChangedCallback,observedAttributes

Статья не об основах веб-компонентов, об этом уже написано достаточно, например вот этот серия статей.


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

Конечно, от этого можно защититься конвенцией именования с использованием префиксов, но такой подход сильно похож на проблемы с именами CSS-классов, избавление от которых нам обещали веб-компоненты.

Гораздо важнее, что проблема с коллизией имен больше не лежит на разработчике компонентов. А разработчик, монтирующий компоненты в свое приложение, сам волен назвать любой компонент — так, как ему удобно его называть. Это так же относится не только к стандарту веб-компонентов, но и к любому фреймворку оперирующему понятием "компоненты" в том же смысле. Как то: React, Vue, Angular, и т.п.

В обычных фреймворках компонент – это класс или функция в Javascript. Оно может быть завернуто в модуль и не должно быть абсолютно уникальным. Вы сможете импортировать две разные кнопки и назвать их по-своему:


import { Button as ButtonA } from 'lib-a';
import { Button as ButtonB } from 'lib-b';

Веб-компоненты регистрируются в общем для всех списке html-тэгов. Если одна библиотека уже заняла имя cool-button, вы ничего уже с этим сделать не сможете.

вы ничего уже с этим сделать не сможете

Можно унаследовать от такого компонента с изменением имени.

Имелось в виду, что если вы подключаете две сторонние библиотеки, каждая из которых хочет использовать имя cool-button, то собрать их вместе на одной странице у вас не получится (не трогая их исходников).

Обычно элементам добавляется какой-то префикс, например здесь добавляют paper.

В статье об этом и говорится, что можно попытаться ввести конвенцию именования. Однако, как показывает опыт CSS, этого недостаточно, конфликты имен все равно случаются. Нужно более непробиваемое решение.
Может хорошей практикой считать не регистрировать компоненты в UI-библиотеках, просто экспортировать класс и пусть использующий сам регистрирует под нужным ему именем. Я все компоненты сам писал так что такой проблемы не было, была проблема с именами атрибутов-свойств: уже существующих свойств дофига, у разных элементов они немного отличаются, плюс немного отличаются от браузера к браузеру. В результате можно легко переопределить существующее имя и получить какой-нибудь непонятный баг.

Регистрация компонентов самому выручит только если они не имеют своих зависимостей. В реальности они у них есть, например paper-input зависит от компонента iron-input. Чтобы не случился конфликт на уровне iron-input, его тоже нужно уметь переопределять...


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


В результате можно легко переопределить существующее имя и получить какой-нибудь непонятный баг.

Здесь помог бы typescript, который бы проверил, что вы используете только правильные свойства. Вот пример. Я пытаюсь определить свойство checked с неправильным типом, и typescript ругается, что такое свойство уже есть в базовом классе.

только если они не имеют своих зависимостей

Ладно, убедили), проблема есть, но всё же при использовании префиксов она совсем незначительна.


Здесь помог бы typescript

Не на 100%, как я уже сказал, браузеры могут добавлять свои нестандартные свойства/методы для элементов.

Я просто не понимаю, почему нельзя сделать так:


import { Button as ButtonA } from 'lib-a'
import { Button as ButtonB } from 'lib-b'

customElements.define('button-a', ButtonA)
customElements.define('button-b', ButtonB)

Это не троллинг, я просто пытаюсь понять, почему вас так беспокоит коллизия имен.

О, теперь понимаю. А как вы бы решили эту проблему?
Сходу я вижу три возможных варианта:


  1. Введение своей области видимости компонентов


    // допустим в конструкторе модуля
    this.customElements.define('button-a', ButtonA)

  2. Вендор-префикс. Это очевидно и это отлично работает в мире PHP (правда не все авторы пакетов соблюдают это правило, но большинство).


  3. Алиасы (это скорее развитие первого варианта)


    customElements.define('element-foo', ElementFoo, {
    aliases: {
      'button-bar' : 'button-baz'
    }
    })


Однако, все эти решения лежат в области ответственности разработчиков модулей. Я что-то так и не смог придумать ни одного варианта с исправлением браузерного api так чтобы стало хорошо.

Первые два варианта – это про решение проблемы путем конвенции именования. Для 10 компонентов это еще сработвает, а для 100, для 1000? Мы это уже проходили с CSS, видно, что на больших масштабах имена не спасают. Но в CSS хотя бы самое страшное что могло случиться – это сломанные стили, то в случае конфликта имен веб-компонентов у вас будет выброшена ошибка в JS и код просто не будет исполняться дальше


Алиасы (это скорее развитие первого варианта)

А вот это может сработать! Примерно так это решается во Vue: Local Component Registration. Но для этого нужно изменить сам веб-стандарт.

На самом деле проблемы совсем не страшные.

  • Tree-shaking и Глобальные имена компонентов — не обязательно регистрировать отдельно и глобально, можно сделать также как сделано в styled components

    import {ButtonElement} from "wclibs/button-element"
    
    const Button = wc.register(ButtonElement);
    ...
    render (<Button/>);
    

    Тогда много проблем сразу отваливается.
  • Проблемы с типизацией — Intrinsic описанный в статье решает проблему.
  • Групповое обновление свойств — это не проблема веб компонентов, это стандартное поведение DOM, а если писать без прослойки с VDOM то и не проблема вовсе.

На самом деле тема очень полезная, у нас большая компания, пишем на разных шаблонизаторах и веб компоненты помогают реюзать компоненты между ними. Но без какой то прослойки типа lit-element крупные вещи действительно лучше не писать.
Tree-shaking и Глобальные имена компонентов

Проблема в том, что API выглядит не так, как вы описываете, а по-другому


customElements.define('button-element', ButtonElement);

где имя компонента обязательно и должно быть уникально в рамках текущего документа.


Кроме того, что делать с транзитивными зависимостями. Вашей кнопке нужен компонент my-icon, кто его будет регистрировать, конечный пользователь или кнопка?


Проблемы с типизацией — Intrinsic описанный в статье решает проблему.

Там же в статье и описаны недостатки. Обновили компонент, поменяли свойства, но забыли обновить Intrinsic. Typescript молчит, а в рантайме все ломается.


это стандартное поведение DOM, а если писать без прослойки с VDOM то и не проблема вовсе.

Вот пример:


const input = document.querySelector('[name="test"]');
input.disabled = true;
input.value = 'bar';

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


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

Тем интереснее узнать, как вы решаете указанные проблемы. Давайте обмениваться опытом :)

API выглядит не так, как вы описываете

Я описал абстрактный сервис который будет заниматься регистрацией веб компонентов и возвращать готовый React компонент для его использования =). А у себя решили просто корпоративным префиксом, что то типо <prefix-button/> и ближайшие пару лет проблем точно не будет.

Обновили компонент, поменяли свойства, но забыли обновить Intrinsic. Typescript молчит, а в рантайме все ломается.

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

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

Нет, он пересчитывает поштучно, именно поэтому виртуальный дом бывает много выгоднее:

var elem = document.querySelector(".post__title_link");
elem.textContent += "1";
console.log(elem.getClientRects()[0].width); // 419.203125
elem.textContent += "2";
console.log(elem.getClientRects()[0].width); // 433.40625


А как вы будете оптимизировать свой собственный компонент?

Я не использую lit-element, у меня своя микро-надстройка. Просто на сеттере свойства я меняю только то что мне нужно, поэтому поведение полностью наследуется от нативного =)

ближайшие пару лет проблем точно не будет

ну что же, вам виднее


Просто на сеттере свойства я меняю только то что мне нужно

Подозреваю, что у вас получилось что-то вроде такого:


class MyButton extends HTMLButtonElement {
   set loading(loading) {
     this.classList.toggle('button-loading', loading)
   }
}

Такой подход сработает на маленьких компонентах. А что, если компонент большой, к javascrtipt-логикой, какое-нибудь dropdown-menu, например, то как с ним быть?

Да именно такая конструкция. Дроп даун очень простой на самом деле. Вот календарь это да.

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

Даже если взять самый умный шаблонизатор, проблема с API все равно останется. Допустим, есть календарь:


const calendar = document.querySelector('my-calendar');
calendar.selectedDate = new Date(2019, 2, 10);
calendar.minDate = new Date(2019, 0, 1);
calendar.maxDate = new Date(2019, 12, 1);

Каждое из этих изменений свойств вызовет ре-рендер, но реально нужен только последний.


Придется городить какую-то оптимизацию, например:


calendar.__renderBlocked = true;
// здесь задаем наши свойства, ре-рендера нет
calendar.__renderBlocked = false;
// здесь произойдет ре-рендер

Или можно сделать асихронное обновление, как в lit-element. Проблема в том, что нет стандартного решения, каждый автор компонента будет делать по-своему.

вопрос будет ли ваша оптимизация работающая на джаваскриптовом рантайме работать быстрее оптимизаций и рендеринга браузерного движка. Я делал бенчмарк 1000000 изменений данных прибинденых к интерфейсу, сравнивая вебкомпоненты + прокси и реакт и редакс. Нативный образец просчитался за 5-6 секунд и отобразил сразу финальное значение, в то время как рякт с пропсами (это был стартер прямо из yeoman) работал несколько минут, сожрал всю память и упал так и не отобразив ни одного изменения

В вашей истории слишком много дополнительных элементов (Redux и его connect), тем более, что это известно, что в yeoman-стартеры любят напихать всякого лишнего для удобства DX в ущерб производительности. Предполагаю, что вы бы получили прирост скорости, даже если бы просто переписали все на ванильный React. Веб-компоненты тут не причем.

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

Я так понимаю, текущее значение счетчика вы через innerHTML рендерили? А как будете рендерить более сложный контент?

да, но правильнее даже наверное .textContent или setAttribute для заменяемых значений, так типобезопаснее и скорее всего прозиводительнее, а основная часть просто должна быть внутри тегов ну если надо динамически еще есть .insertAdjacentHTML()
Или можно делегировать работу с DOM API, отслеживание связей стейта и DOM и т.д. компилятору. Пусть он мучается с этими императивными и не удобными штуками, а мы будем писать высокоуровнево и крайне декларативно. ;-)

Даже если мы напишем идеальный компилятор, то что будет с элементом, который зависит сразу и от minDate, и от maxDate? Он будет обновлен два раза.


Не хватает возможности сказать компоненту "подожди рендериться, мы тебе еще не все данные задали".

Мне почему-то кажется, что это уже микро-оптимизации какие-то. Учитывая, что всекие там реакты/вью вообще отдельно виртуальное дерево строят на каждый пчих, то 2 раза обновить элемент напрямую через DOM API по-любому будет достаточно быстро. Кстати такой компилятор уже есть — Svelte JS называется.

Посмотрел я на Svelte. Там тоже есть нормальный способ обновления всех свойств разом: component.set(state). И в дочерние компоненты это нормально протягивается, тоже всей пачкой.


Это только в веб-компонентах удобного API нет и нужно что-то изобретать

Да, в веб-компонентах забыли предоставить хоть какой-то механизм синхронизации стейта и DOM. Наряду с отсутствием props reflection и нормального SSR, делает область их применения крайне узкой. Я с вашей статьей по большей части согласен. У меня даже доклад есть на эту же тему примерно с теми же консернами.

Кстати, Svelte умеет в веб-компоненты одним булевым флагом и поддержка отличная:

custom-elements-everywhere.com/libraries/svelte/results/results.html

Так что мы просто пишем на нем, в если веб-компоненты таки выстрелят, изменим флажок в конфиге.
Вот так и правильно – пусть веб-компоненты будут деталью реализации фреймворка.

Все-таки основная цель – это писать быстрые и удобные интерфейсы, а не использовать какую-то конкретную технологию, о которой в блоге гугла или фейсбука написали.
это не верное пожелание, дело в том, что на сегодняшний день код на различных популярных фреймворках практически никак между собой не совместим и многие проекты переписываются ежегодно с нуля на очередной сомнительной распиаренной «технологии».
Веб компоненты в свою очередь стандартизированы в виде ряда технологий решающих разные задачи и дающих почти полную замену среднему фронтенд-фреймворку в сумме, также они реализованны во всех современных движках и браузерах, за счет этого они и работают тоже быстрее, не требуя в полифилинга, т.к. загрузки и выполнения лишнего жс кода на старте. Разница когда вы отключили жс-бибилиотеки заметна на глаз даже на простейших примерах.

Ваше описание веб-компонентов слишком идеализированное. Именно для более адекватного представления их возможностей и написана эта статья


дающих почти полную замену среднему фронтенд-фреймворку в сумме

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


они и работают тоже быстрее

По моим измерениям – это не так. Не согласны – приводите свои замеры с цифрами.


загрузки и выполнения лишнего жс кода на старте

Lit-element (использует веб-компоненты) – 6 Кб, Preact (не использует) – 3 Кб. Получается, неиспользование веб-компонентов наоборот уменьшает код?


Разница когда вы отключили жс-бибилиотеки заметна на глаз даже на простейших примерах

Вот этих самых примеров мне и не хватает. Что вы имеете в виду?

для более адекватного представления

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

По моим измерениям – это не так. Не согласны – приводите свои замеры с цифрами.

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

Lit-element (использует веб-компоненты) – 6 Кб, Preact (не использует) – 3 Кб


это минифицированный код, который всеравно будет разбираться джаваскриптовым интерпретатором, в ваших кодах будут ссылки на методы «ядра» из этих библиотек, которые в интепретируемом языке будут делать бестолковые манпипуляции, если вы запускали хоть раз профайлер то видели, что он часто указывает на какую-то одну-две функции используемые повсеместно

Вот этих самых примеров мне и не хватает. Что вы имеете в виду?


реализации технологий веб-компонентов доступны в виде библиотек-заменителей для браузеров в которых они не реализованы, навроде интернет эксплорера 11 (получается то же что с фреймворками), если вы запустите код с билбиотеками, а потом их отключите в современном браузере полагаясь на нативную реализацию, разница в скорости работы может быть заметна без замеров.
Без конкретных цифр звучит неубедительно.
в этом треде я приводил пример когда затык кода на вебкомпонентах разрешился за 5-6 секунд, а рякт работал на том же коде несколько минут пока не сожрал всю доступную память.

Вы можете также нагуглить публичные бенчмарки, я не знаю как они там мерили, но там в числе лидеров веб-компонентный Svelte (https://medium.com/@ajmeyghani/javascript-frameworks-performance-comparison-c566d19ab65b), но тут над понмимать, что этот фреймворк наворачивает свой mustache подобный шаблонизатор над нейтив темплейтами или вовсе без них в рантайме, т.е. занимается тем же бестолковым преобразованием строк в объекты дом с полнотекстовым поиском плейсхолдеров для замены вместо оптимизированного дерева (dom)
Вы можете также нагуглить публичные бенчмарки, я не знаю как они там мерили, но там в числе лидеров веб-компонентный Svelte

Заметил, что вы крайне поверхностно относитесь к своим высказываниям и приводимым примерам.

Для начала, Svelte ни разу не «веб-компонентный». Возможность скомпилировать svelte-компонент в веб-компонент есть, но ей почти никто не пользуется, из-за проблем описанных в данной статье в частности. Есть компиляторы, которые заточены на веб-компоненты, например, StencilJS, но Svelte работает с js классами, а не веб-компонентами.

но тут над понмимать, что этот фреймворк наворачивает свой mustache подобный шаблонизатор над нейтив темплейтами или вовсе без них в рантайме, т.е. занимается тем же бестолковым преобразованием строк в объекты дом с полнотекстовым поиском плейсхолдеров для замены вместо оптимизированного дерева (dom)

Здесь даже незнаешь куда пробу ставить. В Svelte нет никакого mustache-like шаблонизатора над нейтив темплейтами. Более того, он вообще не занимается работой со строками в рантайме, а как раз использует прямые вызовы в DOM API для этого.

Прежде чем писать что-то с уверенным видом, лучше сперва слегка изучить вопрос. Имхо

Lit-element (использует веб-компоненты) – 6 Кб, Preact (не использует) – 3 Кб. Получается, неиспользование веб-компонентов наоборот уменьшает код?

SvelteJS — 0Кб ;)

Я с интересом читал ваши статьи про исчезающие фреймворки, поэтому про магию Svelte в курсе.


Тем не менее там не совсем 0кб, потому что какой-то рантайм все таки грузится. Это примерно как babel-runtime, подключается по мере использования, но измерить его все-таки можно.


Для вашей демки получилось 991 байт gzip. Понятное дело, что это хорошая цифра и к этому нужно стремиться, но это не 0.


Как считал
  1. Собрал бандл с помощью rollup. Конфиг отсюда
  2. Выкинул из него все вхождения своего кода. Имена ключей не минифицируются, поэтому можно его вычислить
  3. Оставшийся бандл минифицируем обратно и смотрим: cat bundle.js | npx terser | npx gzip-size-cli

Так что эти 0* килобайт, они как в той рекламе про жвачку с 0* калорий. Просто из-за методики измерения вышло так.

технологии входящие в веб-компоненты реализованы в браузерах нативно и как следствие вообще не требуют библиотек и работают быстрее
Приятно, что вы читали мои статьи)) Если вдруг будете на HolyJS в мае — велком на мастер-класс, покодим еще.

В целом, с вашим комментарием согласен. Отличие подхода «исчезающих фреймворков», конечно же не в том, что им каким-то магическим образом удалось убрать рантайм из рантайма. Суть в том, что этот рантайм решает лишь задачи вашего приложения, то есть фактически компилятор пишет за нас тот бойлерплейт код, который мы бы сами написали, если бы решали очень конкретную задачу, самым очевидным и простым способом. Без лишних абстракций и решений-комбайнов, подходящих для всех задач сразу. То есть на скриншоте в целом верно написано library: 0Kb, это конечно же не значит, что в рантайме не отрабатывает код.))))

При этом, частые проблемы связанные с множественными связями и «комбинаторным взрывом» решаются машиной с помощью статического анализа и кодогенерации. Чтобы добиться схожей стабильности работы кода, используя те же веб-компоненты и DOM API вручную, нам понадобиться много циклов разработка-багфиксинг-тесты, но машина решает многие вещи намного эффективнее человека.

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

Вы видимо Svelte не посмотрели, тогда бы хоть значи о чем речь. ))) Это как раз фреймворк, который может быть внедрен в любой другой фреймворк. Вот можете даже пример посмотреть тут. Кроме того любой компонент Svelte можно изменением одного флага компилировать в веб-компонент. Поддержка стандарта 100%, выше уже давал ссылку.

Веб компоненты в свою очередь стандартизированы в виде ряда технологий решающих разные задачи и дающих почти полную замену среднему фронтенд-фреймворку в сумме

Основная фича любого современного фреймворка — это ни разу не компоненты и их композиция в виде html-like тегов. Прежде всего, что дают нам фреймворки писать в state-based код, вместо event-based на котором основан весь DOM API. Кроме того, возможность простой и удобной синхронизации стейта и DOM с максимально эффективными манипуляциями в последний. Все это ровно то, чего нет в стандарте веб-компонентов, а то, что там есть не так уж и важно. Например, та же инкапсуляция стилей вполне адекватно решается в CSS Modules или том же Svelte.

Разница когда вы отключили жс-бибилиотеки заметна на глаз даже на простейших примерах.

То то Youtube в Firefox до сих пор тормозит безбожно.
То то Youtube в Firefox до сих пор тормозит безбожно.


полумер полагался на html imports, принятие которых в стандарт заблокировал как раз таки фаерфокс, т.е. там они скорее всего работают через полифил и жс рантайм, а в хроме нативно, вот вам и разница заметная на глаз. Как я понимаю, этот ваш Svelte использует какой-то такой же подход, который был по причинам нарушения принципа разделения ответственностей индустрией отвергнут. Лично мне, точно также кажется обилие странностей фреймворка неоправданным, что-бы завязываться на него. Классы-инстансы для хранения и линковки состояния я могу легко подключить в компоненты с инжектором если что-бы красиво или нехитрым собственным мета-кодом.
полумер полагался на html imports, принятие которых в стандарт заблокировал как раз таки фаерфокс, т.е. там они скорее всего работают через полифил и жс рантайм, а в хроме нативно, вот вам и разница заметная на глаз.

Видите как получается, на стандарт даже Гугл положиться не может, куда уж нам смертным.

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

Боюсь вы не поняли) html imports не используется в Svelte никак, даже близко. Да и то, что они были деприкейтед не имеет отношения к принципу ответственности, скорее к принципу DRY, так как es6 модули и импорты уже завезли.

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

Прикол в том, что на выходе Svelte-компонент это именно класс, причем абсолютно ванильный )) Только писать его в разы удобнее, декларативнее и без убогого и многословного синтаксиса es6 классов.

Видите как получается, на стандарт даже Гугл положиться не может, куда уж нам смертным.

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

Боюсь вы не поняли) html imports

я указал на подобие т.е. механизм импорта вермишели из js, стилей и разметки в html который я увидел в коде для вашего ферймворка, такой же применяется в .vue
в отличии от большого количества неудачных решений популярных и не очень фреймворков.

Например? Фреймворки просто работают и те механизмы, которые они используют зависят только от мейнтейнеров и комьюнити. В это же время, стандарты пишутся комитетатми и рабочими группами от корпораций, а это автоматически добавляет немного корпоративной политики в них. Мое мнение — решения от комьюнити, как правило, более продуманные, удобные и органичные для большнинства разработчиков, чем то, что рождают стандарты. Если бы дело обстояло иначе, небыло бы столько «свистелок» и «сахара» поверх них.

я указал на подобие т.е. механизм импорта вермишели из js, стилей и разметки в html который я увидел в коде для вашего ферймворка, такой же применяется в .vue

То есть по вашему раздел стандрата HTML Import как-то описывал то, как должны писаться Веб-компоненты? Насколько я знаю, это был лишь механизм их подгрузки из html. Не вижу никакой связи с форматом SFC, который используется в Svelte и Vue.
Например? Фреймворки просто работают и те механизмы, которые они используют зависят только от мейнтейнеров и комьюнити.


популярные фреймворки курируются корпорациями навроде фейсбука или гугла и сейчас на фронте все чаще популяризируются неудачные решения и идеи противоречащие принципам программной инженерии, такие как смешение бизнес-логики с версткой, отрицание ооп, игнорирование стандартов. Все современные популярные фреймворки развиваются поперек стандартизированных технологий, в том числе тех, что входят в группу веб-компонентов. Например ангуляр многим хорош, но шаблоны у него свои, а не нативные, и валидацию форм они сделали свою неудобную, когда есть отличное стандартизированное апи хтмл5. У остальных фреймворков проблем еще больше.

То есть по вашему раздел стандрата HTML Import как-то описывал то, как должны писаться Веб-компоненты?


была проектная группа которая разрабатывала стандарты w3c, и html imports тоже предполагался, поэтому использовался в полимере, но он встретил сопротивление и был совсем отвергнут разработчиками фаерфокс например, а затем и вовсе не был утвержден как стандарт
популярные фреймворки курируются корпорациями навроде фейсбука или гугла

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

Ох, вы прям на холиварную тему вступаете…

популяризируются неудачные решения и идеи противоречащие принципам программной инженерии

А разве не инженеры должны решать, что противоречит, а что нет?

такие как смешение бизнес-логики с версткой,

Отличная картинка в тему:
image

отрицание ооп,

А кто вам сказал, что ООП это хорошо? Сколько уже было трудов на эту тему. Это далеко не silver-bullet.

игнорирование стандартов. Все современные популярные фреймворки развиваются поперек стандартизированных технологий, в том числе тех, что входят в группу веб-компонентов.

Не задумывались почему так? Быть может, что-то не то со стандартами, а не со всеми остальными? А то это получается «я один д’Артаньян».

Например ангуляр многим хорош, но шаблоны у него свои, а не нативные, и валидацию форм они сделали свою неудобную, когда есть отличное стандартизированное апи хтмл5.

Отвратная валидации в html5, уж простите.
была проектная группа которая разрабатывала стандарты w3c, и html imports тоже предполагался, поэтому использовался в полимере

Вы капитанить не перестанете, да? Я вас спрашиваю как HTML Importsсвязаны с SFC? HTML Imports вообще не описывали как именно должны описываться Веб-компоненты, которые они грузят.
Вот Polymer курируется Гуглом, значит он популярный?


ангуляр популярный, а react курируется фейсбуком, разе что vue под китайцами и пхпшниками и это тоже сказывается

А разве не инженеры должны решать, что противоречит, а что нет?


конечно, есть шаблоны проектирования, но нынешние фронтендщики любят делать наоборот

А кто вам сказал, что ООП это хорошо? Сколько уже было трудов на эту тему. Это далеко не silver-bullet.


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

Отвратная валидации в html5


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

Я вас спрашиваю как HTML Importsсвязаны с SFC?


они очень похожи, в основе одна и та же идея замешать все в одну кучу поперек инженерного принципа разделения ответственностей, поэтому хтмл импорты и забраковали
ангуляр популярный, а react курируется фейсбуком, разе что vue под китайцами и пхпшниками и это тоже сказывается

Я вас про Polymer спрашивал, потому что я до сих пор пытаюсь понять ваши критерии «популярности». Выше вы написали, что «популярный — значит ходит под корпорацией». Polymer значит популярный, а Vue например пишет в основном Эван до сих пор, то есть он по-вашему менее популярный.

конечно, есть шаблоны проектирования, но нынешние фронтендщики любят делать наоборот

Я, например, инженер с профильным высшим и 12+ стажем, первые языки C/C++. Первые проекты тяжелые телекоммуникационные системы. И что? Современный веб фронтенд — это то, чего не существовало, когда разрабатывались классические паттерны и многие из них вообще не ложатся на современый веб. Считаю что поиск аутентичных решений — это верное направление, тем более что многие их них уже показали свою эффективность. В отличии от классического ООП для веба.

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

Я не фанат чистой функциональщины, но вы хоть знаете чем процедурный подход отличается от функционального?
вполне достаточная что-бы решать задачи, а в ангуляре нельзя явно вызвать метод валидации, только сбиндить, в результате чего сложный валидатор сделать больно

Эта одна из причин, почему Angular по-сути единственный современный all-in-one фреймворк. Остальные давно поняли, что лучше использовать специализированные, независимые и узконаправленные решения для каждой задачи.

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

Хватит нести отсебячину, спеку почитайте пожалуйста, вот вам ссылка даже: HTML Imports spec

Еще раз, спека по HTML Imports никак не описывает каким именно образом должны писаться веб-компоненты, а отменили ее не из-за того, что вы пишете, а из-за ES6 модулей. Не вводите людей в заблуждение, пожалуйста.

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


как это показали? я видел только, что никто за фронтендщиками не хочет проекты продолжать а они все время переписываются на очередной казуальной погремушке

Эта одна из причин, почему Angular по-сути единственный современный all-in-one фреймворк.

каждый фреймворк из популярной тройки — велосипедный all-in-one, никто не использует редакс с вуе и т.п.

Еще раз, спека по HTML Imports никак не описывает каким именно образом должны писаться веб-компоненты, а отменили ее не из-за того, что вы пишете, а из-за ES6 модулей.


использование импортов предполагало размещение всего в одном файле как .vue или .svelte и полключение одной строкой, es6 модуль предполагает что вы с этим «бандлом» что-то сделаете все-таки явно, отрендерите или задефайните
я видел только, что никто за фронтендщиками не хочет проекты продолжать а они все время переписываются на очередной казуальной погремушке

Может им просто хочется новую экспертизу заиметь? Учитывая, что почти все фреймврки нынче компонентные и юзают ± одни и те же подходы, мне кажется не логичным вывод, что подходы плохие, раз потом все это переписывается на другом фреймворке, но тех же подходах.

никто не использует редакс с вуе

Вы где были последние пару лет то? Те кому нравится Redux (я к таким не отношусь) пишут на нем, даже со Svelte, например, svelte-redux. И это не смотря на то, что в Svelte свой встроенный глобальный стор есть.

использование импортов предполагало размещение всего в одном файле как .vue или .svelte и полключение одной строкой, es6 модуль предполагает что вы с этим «бандлом» что-то сделаете все-таки явно, отрендерите или задефайните

А веб-компоненты типа не предполагают? Сколько не видел, что пишут люди, всегда разметка и стили внутри класса-компонента. Вот хоть статьи i360u почитайте, он ведь спец.

Вы где были последние пару лет то? Те кому нравится Redux (я к таким не отношусь) пишут на нем, даже со Svelte


есть не значит что им пользуются, у них своих 5 погремушек «аналогов» с другими анти-патернами, например они там все файлы называют одинаково

А веб-компоненты типа не предполагают? Сколько не видел, что пишут люди, всегда разметка и стили внутри класса-компонента.


веб компоненты это еще и нейтив темплейы, которые позволяют не инлайнить вертску в джаваскрипте, то что некоторые все-таки инлайнят это влияние реакта и антипатерн конечно
есть не значит что им пользуются, у них своих 5 погремушек «аналогов» с другими анти-патернами, например они там все файлы называют одинаково

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

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

А работать с найтив шаблонами нельзя из класса компонента что ли? Вообще то именно так часто и делают, потому что юзают их не помещая на страницу сразу как в выгребную яму, а через DOM API. Мне почему-то кажется, что лет 6 назад вы шаблоны писали примерно так:

<script type="text/html" id="template">
 <!-- html here -->
</script>


Прям чувствуется влияние jquery.
Лично я считаю, что если у разработчиков есть выбор — это хорошо.

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

Мне почему-то кажется, что лет 6 назад вы шаблоны писали примерно так:


я писал как в svelte с {{ плейсхолдерами }} и {# циклами #}, сейчас я думаю что это все лишнее когда есть native templates и компонеты кастомных элементов
что на сегодняшний день код на различных популярных фреймворках практически никак между собой не совместим

Вы видимо Svelte не посмотрели, тогда бы хоть значи о чем речь. )))


svelte не является популярным фреймворком, я имел ввиду react, vue, angular, если вы записанное простыми предложениями понять не можете я вам помочь ничем не смогу
Цитирую вас:
на различных популярных фреймворках

Тут нигде не указано что вы говорите о фреймворках Большой Тройки. Если бы вы хотели конкретизировать, то наверное написали бы этот довольно распространенный термин. Кроме того, «популярность» — это оценочная величина. Вот, к примеру, Ember по-вашему популярный фреймворк? А Preact? По мне так, учитывая какое кол-во всевозможных решений пылится на полках Gihub, если о фреймворке говорят, у него есть активное комьюнити и он развивается, то его вполне можно отнести к «различным популярным фрейморкам».

Остальное все оправдательная демагогия, призванная скрыть вашу неосведомленность о подобных решениях.

Тут нигде не указано что вы говорите о фреймворках Большой Тройки.


ну svelte к ним точно сейчас не относится, ember наверное уже не относится, про preact я слышал только от поклонников реакта, так что тоже наврядли, действительно можно говорить только о трех фреймворках на сегодня
ну svelte к ним точно сейчас не относится

К кому ним? Как вы оцениваете популярность?
ember наверное уже не относится,

Вот видите как, а в штатах очень популярный фреймворк, особенно в средних и крупных проектах. До сих пор и очень неплохо развивается.

действительно можно говорить только о трех фреймворках на сегодня

Это лишь ваше субъектиное суждение. Я не обязан читать ваши мысли.
оптимизация, которой вы так боитесь, в древние времена была сама собой разумеющейся.
Даже на Win32 и VCL, если надо менять сложный компонент или много рисовать — отключил отображение, поменял все свойтсва/посчитал что надо — включил отображение и перерисовал.
Почему вам кажется это сложным — не понятно. Ни один фреймворк не сможет определить вот сейчас вы одно свойство меняете, вот там — будет 20.
В том-то и дело, что даже на Win32 и VCL была возможность приостановить рендеринг, а здесь ничего из коробки нет.
UFO just landed and posted this here
lit-element использует самый обычный lit-html, здесь скорее вопрос терминологии.

Под VDOM имеется в виду то, что обновление компонента происходит не грубым element.innerHTML, а каким-то более умным способом. Каким именно – неважно.

У вас есть какое-то лучшее слово для всего этого семейства технологий «умных обновляетелей DOM»?
Например, «эффективные манипуляции в DOM». Все же термин VDOM — оносится к совершенно опредеенному способу работы с DOM и конечно же в lit-html никакого VDOM нет. Мне кажется упоминание VDOM в контексте lit-element/lit-html немного вводит в заблуждение.
Обновил формулировки в статье, спасибо за фидбек!

Но моё мнение остается тем же: когда lit-html заявляет: «мы не VDOM!» – это просто такой маркетинг, чтобы привлечь больше пользователей, которые по каким-то причинам не хотят React. Да, есть некоторые отличия под капотом, но это детали реализации, для пользователей библиотеки разницы нет.
для пользователей библиотеки разницы нет

все vdom реализации как минимум предоставляют два примитива: динамический список чилдренов и динамические атрибуты. Первое в lit-html есть, второе отсутствует https://github.com/Polymer/lit-html/pull/213 .

Спасибо за информацию! Но, кажется, недостающая фича ещё больше уменьшает смысл lit-html и его подхода
У lit-html как минимум есть смысл в том чтоб проверить теорию о том насколько эффективно такой подход будет работать на кэйсах с маленьким количеством динамических биндингов (простые веб приложения). Но на данный момент они как-то умудрились в этом бэнчмарке[1] во всех тестах показывать результаты хуже чем у vdom библиотеки, хотя в этом бэнчмарке они должны быть в выигрышном положении так как здесь практически нет динамических биндингов, не требуется использовать композицию и можно просто клонировать большой кусок dom'а и в дополнение они ещё абузят event delegation[2].

1. krausest.github.io/js-framework-benchmark/current.html
2. github.com/krausest/js-framework-benchmark/blob/e469a62889894cb4d4e2cac5923f14d91d1294f8/frameworks/keyed/lit-html/src/index.js#L126
И все же vdom — это vdom. Это далеко не общий термин и он ни разу не обобщает подходы к повышению эффективности манипуляций в DOM. В том же Angular vdom нет, в Svelte тоже его нет, также как в lit-html, при это все они пытаются делать изменнения в DOM максимально эффективно. Полагаю без таких вещей как render virtual tree & reconcile, считать что-то vdom значит намеренно сужать разнообразие подходов. Именно в vdom полно маркетинга, поэтому многие молодые разработчики думают что на vdom свет клином сошелся.
Большая часть тезисов и выводов данной статьи весьма спорна, это мягко говоря. С веб-компонентами нет никаких особых проблем ни с контролем зависимостей (реестр компонентов дает вам всю необходимую информацию о том, что вы регистрируете в рантайме в любое время), ни с типами (вы вполне можете писать свой код на TS и создавать тайпинги для своих тегов) ни, тем более, с производительностью (автор бы сравнил скорость рендера с react/vue-компонентами, справедливости ради, а еще сам код можно разобрать по косточкам, ибо в нем речи не идет о компонентах, сравнивается теплое с мягким). Сфера применения указана также весьма странно, видно что автор копнул тему но явно недостаточно глубоко. Про VDOM тоже ерунда написана, в подходе с веб-компонентами вам вообще не обязательно иметь какие-либо промежуточные сущности между DOM и данными, вы можете производить инъекции максимально эффективно через старый добрый DOM API. Очень не советую рассматривать данную статью как какое-либо руководство к действию. Но с тем, что веб-компоненты это не замена фреймворкам, конечно, стоит согласиться, их скорее стоит рассматривать как основу для фреймворков нового типа, а также как композиционную основу для построения собственных велосипедов. В этой роли — они великолепны.
автор бы сравнил скорость рендера с react/vue-компонентами, справедливости ради

Вот две демо-страницы. Рендерится выпадающий список с 2000 элементов.



В случае lit-element в последнем Хроме я наблюдаю явную просадку FPS при открытии меню. В Preact-версии такого нет. Исходный код демок можно посмотреть вот здесь.


вы вполне можете писать свой код на TS и создавать тайпинги для своих тегов

Как это сделать? Самое лучшее, что я нашел – это поддержка типов в Stencil, но она далеко не дотягивает то того, что я получаю с React.


Про VDOM тоже ерунда написана, в подходе с веб-компонентами вам вообще не обязательно иметь какие-либо промежуточные сущности между DOM и данными

VDOM иметь не обязательно, но для больших компонентов сильно желательно. Если компонент содержит внутри больше пары html-тэгов, то императивно обновлять их будет неудобно. Подробнее уже раскрыто в этой ветке комментариев.


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

Что не так со сферой применения? Есть еще какие-то неперечисленные варианты?

В случае lit-element в последнем Хроме я наблюдаю явную просадку FPS при открытии меню. В Preact-версии такого нет. Исходный код демок можно посмотреть вот здесь.


lit-element это не совсем веб-компоненты, это штука больше похожая на react и видимо от тех же проблем страдающая, а метод рендеринга собственно веб-компонентов это Native Templates, когда вы клонируете экземпляр шаблона и апендите, это работает намного быстрее любого шаблонизатора, потому что на момент работы жс рантайма шаблон уже разобран браузером и не нуждается в значительных рендеринг операциях
Возможно. Обновил демку из статьи, чтобы можно было сравнить Preact с ванильным подходом: web-components-eesuvphctg.now.sh Preact держится на уровне обычного DOM, Shadow DOM отстает.

Попробовал добавить использование template-элемента, разницы никакой: web-components-vbrhqgtead.now.sh Видимо, на таких маленьких размерах html это особой роли не играет.
в вашем примере вы в рантайме создаете шаблон, когда оптимальнее для производительности разместить его сразу в html, тогда он будет разобран браузерным движком раньше и быстрее и быстрее, затем вы там основную работу делаете строками, т.е. преимущества собственно шаблонной технологии не используются

Создание шаблона происходит за пределами измеряемого отрезка, так что разницы никакой.


затем вы там основную работу делаете строками

А как ее делать иначе, если контент для разных элементов отличается?

если сильно отличается это должны быть разные шаблоны, каждый из этих шаблонов вы уже имеете в объектной модели браузера, быстро и дешево клонируете и подрендериваете динамические данные, тут надо понимать, что вам не обязательно перерендеривать что-то или даже все, на каждое изменение, т.к. вы можете сбиндить логику делающую простую перезапись данных по ссылке при проявлении изменений в системе.
Во первых, ситуацию с LitElement — некорректно экстраполировать на веб-компоненты в целом. Эта либа написана извращенцами любителями функционального подхода в применении к глубоко «объектным», по своей сути, DOM-элементам, коими и являются веб-компоненты. Разница — в парсинге шаблонов: есть очень быстрый нативный парсинг (innerHTML до начала отрисовки компонента), и есть парсинг шаблонных строк в js, с разделением на чанки, складыванием в память точек вставки для биндингов и т.д. (как в lit-html). Априори второй способ медленнее. Также, именно по этой причине, любой фреймворк, основанный на близком подходе будет медленнее примерно раза в 2 (и больше) чем при использовании нативного парсинга шаблона до вставки элемента на страницу. Сделаю акцент: мы говорим о первичной отрисовке, есть еще апдейты отражающие измененные данные. Скорость этих апдейтов отличается не так радикально, но прямые изменения через свойства типа textContent будут также быстрее чем отложенный рендеринг в LitElement (процентов на 10, судя по моим тестам). По вышеописанным причинам, мне очень не нравится тот путь, который выбрали разработчики Polymer, хотя они и говорят о работе «со скоростью молнии».

Во вторых: сделайте, наконец, корректный тест. Отобразите на странице 1000 компонентов, обязательно с одинаковой структурой, созданных с помощью LitElement, React и на чистых компонентах. Вы сами все увидите.

Как это сделать? Самое лучшее, что я нашел – это поддержка типов в Stencil, но она далеко не дотягивает то того, что я получаю с React.


Если компонент добавляется в разметку через парсинг html, то вот: github.com/Microsoft/vscode/issues/62976
Если через импорт и ключевое слово «new», то также как и везде, когда вы используете кастомные типы.

VDOM иметь не обязательно, но для больших компонентов сильно желательно


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

Что не так со сферой применения? Есть еще какие-то неперечисленные варианты?


Ага, есть. Мы уже, насколько я помню, об этом говорили: habr.com/en/post/422499
> Также, именно по этой причине, любой фреймворк, основанный на близком подходе будет медленнее примерно раза в 2 (и больше) чем при использовании нативного парсинга шаблона до вставки элемента на страницу.

Можете продемонстрировать это на каком-нибудь примере?
Я конечно понимаю, что когда делаешь заявления о 2-кратной разнице в скорости, это обязывает к представлению доказательств. Но не думаю что их стоит мне оформлять в качестве ответа на коммент. Я написал на эту тему собственную либу и хочу посвятить ей отдельную статью, где и приведу все тесты. На оформление потребуется какое-то время, там очень много всего. Тем не менее, вы сами можете все легко проверить: lit-element.polymer-project.org/guide/start
Тем не менее, вы сами можете все легко проверить: lit-element.polymer-project.org/guide/start

К сожалению полимеровцы так же любят рассказывать о высокой производительности, но при этом никогда не показывают реальных цифр :) С нетерпением жду вашей статьи с реальными цифрами.

полимеровцы уже отказались от развития своих придумок в пользу lit-html, это было благородно наверное, если бы lit-html сам по себе не был таким же поперек придуманным относительно веб компонентов
Простите великодушно, я не гугл, у меня нет ни собственного пиар-отдела ни полчища разработчиков на подхвате. Тесты — это вопрос вовсе не такой простой как может показаться на первый взгляд. В текущей ситуации мы равны: вы, также можете проявить инициативу и поиграть с примерами сами. Кроме того, я довольно подробно изложил причину разницы в производительности. Готовы с этим поспорить?
> Готовы с этим поспорить?

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

github.com/zakangelle/generator-redux-stack

и поменяйте так что-бы он делал миллион инкрементов (изменений) при нажатии кнопки, никакой особой магии просто иммитация значительной работы в режиме SPA, и вам не нужны будут никакие бенчмарки
Беру тормозной virtual dom, традиционный бэнчмарк с кучей апдэйтов dbmonster[1], смотрю на профайлер в хроме и вижу «85.72% (program)». Чо оптимизировать то?

1. localvoid.github.io/ivi-examples/benchmarks/dbmon/?m=1
да, течет и жрет ресурсы единственно возможного в одном потоке ядра хоть и не так быстро как было у меня с реактом и редаксом, это миллион апдейтов:)?
вот код который делает миллион апдейтов на нативе, но его браузерый рантайм оптимизирует и он выполняется за 5-6 секунд сразу показывая финальный результат%)
        let data = { foo: 'bar'};
        let template = document.importNode(document.getElementById('comp-template').content, true);

        let container = document.getElementById('container');
        container.appendChild(template);
        let dataEl = container.querySelector('#data');

        let dataProxy = new Proxy(data, {
            set(target, prop, value) {
                target[prop] = value;
                dataEl.innerHTML = value;
                return true;
            }
        });

        (function() {
            console.log('starting ..');
            var i = 0;
            console.log(bench(() => {
                dataProxy.foo = ++i;
            }, 1000000, [], this)); // 1 million updates == 8.3 secs
        })();
Что это за странный юзкэйс? Зачем вы трогаете innerHTML у одного элемента 1 миллион раз за фрэйм. Все современные декларативные библиотеки умеют батчинг.
А еще батчинг умеет сам браузер, и делает это оптимальнее js.
А ещё нужно показывать цифры прежде чем продолжать делать различные заявления.
я трогаю не элемент а прокси объект, вообще я сделал такой же точно по входным тербованиям пример на реакте (вызывал инкремент у редакса) и он выжирал всю память и заваливал вкладку не обновив значение ни разу, потом я его упростил убрав функцию бенчмарка, но ничего не поменялось, для меня этот код выглядел вполне естественным. У меня сложилось гипотеза, что в случае с нативом браузер оптимизировал цикл высчитав финальное значение и отрисовав сразу, но продолжая колбасисть код бенчмарковых фукнций 1000и раз и в случае с реактом он этого сделать не смог, а может быть пытался построить какую-то оптимальную цепочку рекурсивного вызова своего инкрементального рендера
> вообще я сделал такой же точно по входным тербованям пример на реякте (вызывал инкремент у редакса)

То что вы сделали на реакт+рекдакс скорее всего отрабатывало инкремент экшен в редаксе, вызывало синхронный запуск реконсайлера и обновление DOM элемента миллион раз. Не понимаю что вы там пытались протестировать таким образом, не существует реальных юзкэйсов когда нужно обрабатывать много различных редакс экшенов за один фрэйм, такое ощущение что вы не понимаете как используется redux.
я думаю дело не только во мне, а еще и в том, что в браузерном одном потоке нет настоящей асинхронности, и он не мог сделать выход из цикла, что-бы запустить редаксо-реактовую магию биндинга, а в случае в нативным кодом все-таки оптимизировал сам цикл. Честно говоря, я бы хотел как-то сравнить реакт и вебкомпоненты (натив), но не понимаю как сделать это справедливо учитывая, что у вебкомпонентов нет ориентированности на перерендеринг компонента и задачи биндинга и рендеринга можно решить без архитектурно-алгоритмических ухищрений
> и задачи биндинга и рендеринга можно решить без архитектурно-алгоритмических ухищрений

Традиционный клиент-сервер юзкэйс когда сервер отправляет снэпшоты данных невозможно решить без дифф алгоритма, тк отсутствуют какие-либо данные о том как нужно переставлять дом элементы чтобы прийти к конечному состоянию. Если будете обновлять с помощью innerHTML, то потеряете внутреннее состояние всех компонентов.
когда есть геттеры/сеттеры и прокси, зачем вам дифф алгоритм? изменять данные и связи всегда дороже чем создавать новую копию на основе старых и этого изменения, а у компонентов и не должно быть состояния, которое нельзя потерять вместе с компонентом
да этот пример просто расширить скорее всего не выйдет, а вот на хорошо структурированный код angular-material/cdk я легко менял под свои задачи наследуя, расширяя и переопределяя классы компонентов, шаблоны, не переписывая весь грид с нуля, не копипастя и даже не особенно вникая во внутреннее устройство. В этом главная задача технологий — быть расширяемыми и доступными для участия в доработке и развитии другими людьми желательно не сильно завися от моды.
Причём тут расширить? Это простой пример когда приходит снэпшот данных и нужно обновить DOM структуру, не теряя внутреннее состояние. ~60 строчек кода на любой современной библиотеке, вот к примеру тоже самое на React[1]. Реализуйте тоже самое поведение без использования библиотек вроде lit-html, это ведь так легко «когда есть геттеры/сеттеры и прокси».

1. github.com/localvoid/uibench-react/blob/master/js/fc.jsx
а вы уверенны, что это внутреннее состояние компонентам необходимо? мне кажется это всеравно что пытаться кастомные элементы постоянно себя целиком перерендеривать с диффом как в рякте
> а вы уверенны, что это внутреннее состояние компонентам необходимо?

пусть будет внутреннее состояние элементов: css анимации, позиция скролла, позиция курсора в инпут полях, документ в ифрэйме, медиа элементы и куча других кэйсов.
эти параметры уже существуют в базовых элементах и лучше как раз через сеттеры геттеры их смапить прямо или менять через евенты, а не хранить. Так или иначе веб-компоненты вас в этом никак не ограничивают, как вам кажется необходимым так и можно сделать, единственно, что какие-то арихитектуры навроде реактовской я бы бездумно воспроизводить не стал, т.к. они придумывались как ответ на кашу-вермишель фронтенд технологий 10и летней давности, а с вебкомпонентами все поменялось и браузер может сам решать задачи сборки мусора или оптимизации
т.е. даже если бы этот код не тек, а делал все быстрее всех, толку от него как от выгравированной в камне веб-страницы
Во вторых: сделайте, наконец, корректный тест. Отобразите на странице 1000 компонентов, обязательно с одинаковой структурой, созданных с помощью LitElement, React и на чистых компонентах.

https://web-components-eesuvphctg.now.sh


Участвуют vanilla.js, shadow-dom и preact. Vanilla и preact держатся на одном уровне, shadow dom остает. Исходники

Ну в вашем тесте снова нет ни одного веб-компонента… Зачем вы раз за разом это повторяете? Вы добавляете Shadow DOM в параграф!!!, и используете элементы списка которые могут вызывать сайд-эффекты, поскольку имеют свои стили по умолчанию в браузере. Зачем? Вы добавляете дополнительный элемент со стилями в Shadow DOM а это уже никак нельзя считать эквивалентом по структуре. В одном случае вы сначала создаете элемент, затем для него вызываете innerHTML, в другом размещаете все целиком в шаблоне. Это по вашему корректный тест? Можно просто сделать что-то типа
<div><span>First Name</span> <span>Second Name</span></div>

и завернуть это в компоненты по стандарту?
Еще упустил, в случае с preact у вас все элементы рендерятся просто внутри шаблона ОДНОГО компонента по сути… Это честно по вашему?
Я пишу код так, как я бы его писал в реальном проекте. Если есть похожий паттерн на веб-компонентах, давайте его тоже использовать.
Вот пример на скорую руку:
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>WC Test</title>
</head>
<script type="module">
class TestElement extends HTMLElement {
  constructor() {
    super();
    this.name = 'John';
    this.secondName = 'Snow';
    this.attachShadow({
      mode: 'open',
    });
    this.shadowRoot.innerHTML = `
      <style>
        :host {
          display: block;
          color: red;
        }
      </style>
      <span>${this.name}</span> <span>${this.secondName}</span>
    `;
  }
}
window.customElements.define('test-element', TestElement);
</script>

<body>
  <script type="module">
    let startTime = window.performance.now();
    let elemetsTotal = 1000;

    for (let i = 0; i < elemetsTotal; i++) {
      let tEl = document.createElement('test-element');
      document.body.appendChild(tEl);
    }

    window.requestAnimationFrame(() => {
      console.log('Elements total: ' + elemetsTotal + '; Rendering time: ' + (window.performance.now() - startTime) / 1000 + 's');
    });
  </script>
</body>

</html>
Запустил ваше демо, получил рендеринг за 0.307s.

Собрал свое демо на preact, получил 0.108s

Код примера
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Preact Test</title>
    <script src="https://unpkg.com/htm@2.1.1/preact/standalone.js"></script>
  </head>
  <style>
    .element {
      display: block;
      color: red;
    }
  </style>
  <script>
    const { html, Component } = htmPreact;
    class TestElement extends Component {
      render() {
        return html`
          <span class="element">
            <span>${this.props.name}</span> <span>${this.props.secondName}</span>
          </span>
        `;
      }
    }

    function App({ elementsTotal }) {
      return html`
        <div>
          ${Array.from(
            { length: elementsTotal },
            (_, index) =>
              html`
                <${TestElement}
                  key=${index}
                  name=${"John"}
                  secondName=${"Snow"}
                />
              `
          )}
        </div>
      `;
    }
  </script>
  <body>
    <script type="module">
      let startTime = window.performance.now();
      let elementsTotal = 1000;

      htmPreact.render(htmPreact.h(App, { elementsTotal }), document.body);

      window.requestAnimationFrame(() => {
        console.log(
          "Elements total: " +
            elementsTotal +
            "; Rendering time: " +
            (window.performance.now() - startTime) / 1000 +
            "s"
        );
      });
    </script>
  </body>
</html>


этот тест не учитывает особенность реактоподобных фреймворков перерендеривать компоненты зря, например когда я открываю фейсбук у меня начинает расти потребление памяти до гигабайтов и паедаться до 5 % core i7 даже при бездействии
Память кушают только фреймворки основанные на vdom, потому что они строят деревья в памяти. Компонент React, кроме этого, пытается быть чистой функцией от стейта, что тоже приводит к лишним действиям, если вручную не оптимизировать эти процессы. Тот же Svelte, у которого нет vdom, не имеет таких изъянов в потреблении памяти, хотя по вашей логике, это тоже реактоподобный фреймворк. Можете сами убедиться:



Svelte тут староват конечно. В 3-й версии были сделаны многие улучшения, но в целом сути это не меняет.
Для интереса взял ваш код и код justboris для Preact, а также написал и собрал тоже самое на SvelteJS и запустил все на своей машине.

Реализация на Svelte 3
# Компонент Test
<div>
  <span>{name}</span> <span>{secondName}</span>
</div>

<script>
  let name = 'John', secondName = 'Snow';
</script>

<style>
  div { display: block; color: red; }
</style>

# Компонент App
{#each Array.apply(null, { length }) as _}
<Test />
{/each}

<script>
  import Test from './Test.svelte';
  export let length = 0;
</script>

# main.js
import App from './App.svelte';

const startTime = window.performance.now(),
  length = 1000;

const app = new App({
  target: document.body,
  props: { length }
});

window.requestAnimationFrame(() => {
  console.log(`
    Elements total: ${length}; 
    Rendering time: ${(window.performance.now() - startTime) / 1000}s
  `);
});

export default app;



Запустил эти 3 примера по 5 раз, каждый раз с отчисткой кэша и жесткой перезагрузкой. Машинка Macbook Pro 2015 года. Последний Хром.

В итоге имеем:

# WC
Rendering time: 0.3918650000123307s
Rendering time: 0.42027000000234693s
Rendering time: 0.3281399999978021s
Rendering time: 0.28746000002138317s
Rendering time: 0.36329000000841916s


# Preact
Rendering time: 0.1805400000885129s
Rendering time: 0.19557999994140118s
Rendering time: 0.16606499999761581s
Rendering time: 0.2203999999910593s
Rendering time: 0.18056499992962927s


# Svelte
Rendering time: 0.12924999999813735s
Rendering time: 0.13404000003356487s
Rendering time: 0.12390500004403293s
Rendering time: 0.12220999994315207s
Rendering time: 0.13685499993152916s


Вывод:

Ваш пример не подтверждает ваши же тезисы. Не похоже что веб-компоненты работают быстрее. Из плюсов WC то что в браузер была доставлена лишь html-ка весом 1.3Kb.
В то же время, Preact доставил в браузер 1.7Kb html и 3.8Kb js кода, а Svelte доставил 483B html и 3.9Kb js кода.

вы ведь используете там преобразование строки (да еще и с интерполяцией) с разметкой в dom, а не нейтив темплейты, т.е. замеряете не то. Кроме, того вы это запускаете в эдже? Зачем там мета совместимости?
вы ведь используете там преобразование строки (да еще и с интерполяцией) с разметкой в dom, а не нейтив темплейты, т.е. замеряете не то.

Я никаких преобразований строк не делаю. Да и непонятно, почему я должен использовать найтив темплейты? И при этом с какого-то перепугу замеряю не то.

Все просто, я взял пример от уважаемого i360u на веб-компонентах и пример от уважаемого justboris на Preact. Пример был придуман не мной, поэтому я действовал в предложенных обстоятельствах и просто реализовал подобную вещь на Svelte. Далее я запустил все 3 примера в абсолютно равных условиях, равное количество раз и опубликовал результаты.

Если у вас есть более «правильный» пример для замеров, то можем и его обсудить.

Кроме, того вы это запускаете в эдже?

В моем комментарии достаточно точно написано на чем я запускаю:
Macbook Pro 2015 года. Последний Хром.

Зачем там мета совместимости?

О чем вы вообще?
а и непонятно, почему я должен использовать найтив темплейты? И при этом с какого-то перепугу замеряю не то.


потому, что нейтив темплейты входят в группу стандартов объединенных термином, веб компоненты, а вы замеряете вставку строки с интерполяцией в dom и называете это веб-компонентами

О чем вы вообще?


строка включает движок эджа, зачем такое в тестах?
потому, что нейтив темплейты входят в группу стандартов объединенных термином, веб компоненты, а вы замеряете вставку строки с интерполяцией в dom и называете это веб-компонентами


В каком именно месте я замеряю вставку строки с интерполяцией в dom? В упор не вижу.

строка включает движок эджа, зачем такое в тестах?

Какая строка? Будьте, пожалуйста, конкретнее. Знаете, но люди не умеют читать ваши мысли.
Какая строка?

http-equiv=«X-UA-Compatible» content=«ie=edge»

весь этот пример основан на записи строки в которую интерполяцией подставляются значения через свойство .innerHTML, т.е. этот тест не проверяет веб-компоненты, а как максимум часть называющуюся Custom Elements, поэтому что если вы откроете любую статью или книгу про веб-компоненты вы там увидите и упоминания Native Templates т.е. шаблонов в теге template клонируемых в dom
http-equiv=«X-UA-Compatible» content=«ie=edge»

В каком месте моего кода вы увидели это метатег?

весь этот пример основан на записи строки в которую интерполяцией подставляются значения через свойство .innerHTML, т.е. этот тест не проверяет веб-компоненты, а как максимум часть называющуюся Custom Elements, поэтому что если вы откроете любую статью или книгу про веб-компоненты вы там увидите и упоминания Native Templates т.е. шаблонов в теге template клонируемых в dom

Ко мне какие претензии? Тут в треде есть уважаный i360u, который судя по его статьям считает себя супер-специалистом по веб-компонентам. Выше он доходчиво объяснял уважаемому justboris почему его тесты не верны, а потом написал свой вариант, который я и использовал.

Вы мне предлагаете тыкать его носом в его же реализацию? Извините, я по-другому воспитан.

хорошо, он неправильно тестирует веб компоненты:)
Ему об это и напишите, мне то зачем? Я и не могу понял, где вы в Svelte нашли работу со строками. Ее там не то что в рантайме, даже при компиляции нет.
UFO just landed and posted this here
для не SPA это не проблема, что-бы все необходимые темплейты находились в одном хтмл, кроме того в фронтенд-фреймворках довольно модная тема — server side compilation, где по роутам создаются предкомпилированные бандлы, так что тут как с роутингом и инжекцией зависимостей все на совести разработчиков фреймворков
UFO just landed and posted this here
Мы уже внезапно и не про SPA оказывается общаемся

веб-компоненты позволяют использовать их и так и этак, поэтому они останутся жить, а фреймворки в которых это надо делать через нахлобучки уже теряют своих поклонников.
Вот я могу так в Svelte делать:

<template src="./templates/MyComponent.html"></template>
<script src="./scripts/MyComponent.js"></script>
<style src="./styles/MyComponent.css"></style>


Это считается? Все отдельно, как вы советуете.
да, так правильнее конечно
UFO just landed and posted this here
тут кто-то ругал custom elements за глобальное пространство имен, вот разве html imports не тот же настоящий глобал? как быть с потенциальными уязвимостями? вдруг кто-нить трояна в килотонны вермишели засунет? у схожего по смыслу iframe сейчас сделали очень много ограничений по безопасности в силу этой проблемы
UFO just landed and posted this here
я пихаю все шаблоны в разные файлы, т.к. разрабатывал с сервер-сайдными технологиями%)
UFO just landed and posted this here
эм, что вам мешает сделать пример с тегом template и importNode/clone? почему я должен бежать что-то делать для вашей прихоти, особенно если вы сам сделали неправильно
UFO just landed and posted this here
это пример использования двух шаблонов, а код прикладной, а не продуктовый, примеры переносимых есть в бибиотеках-компонентах на webcomponents.org и прочих
UFO just landed and posted this here
разгребать это когда проект на нмп даже не собирается в девелопмент режиме, так что я уже сочувствую тому кто за вами будет разгребать
UFO just landed and posted this here
да не только, фронтенд откровения это всегда мрак, хорошо еще, что у многих официантов просто скилла и буджета не хватает, что-то отличное от шаблона выдумать, но поскольку популярные фреймворки сами по себе страшны в нарушениях инженерных практик от этого не так что-бы легче
Короче, все все поняли. Вы просто не шарите и отстали от жизни. Давайте только не будем наращивать вашу экспертизу за счет комментариев на Хабре. Пойдите чтобы курсы какие-то онлайн пройдите что ли. Тогда глядишь и npm освоите.
Если что, я имел ввиду чисто фронтенд. Предполагаю, что у вас есть опыт в серверной части. С некоторой вероятностью это что-то вроде Javа или .NET. Думаю отсюда, более-менее позитивное отношение к Angular и негативное отношение к остальным фреймворкам. Ну и конечно же все эти загоны про ООП и паттерны.
я работал со большинством популярных фронтенд (и бекенд, да) технологий за последние лет 10, мое негативное отношение к остальным фреймворком объясняется только их низким качеством и стремлением игнорировать стандарты и паттерны и колхозить ерунду вместо этого. Для старых фреймворков это объяснимо, т.к. джаваскрипт был сам по себе убог и казуален, но теперь такими стали и сами фронтенд разработчики и весь их даже современный код. Кроме того, фронтенд восновном контролируется группировкой комплиментарных микрософту корпораций и вообще разработчиков, а они паталогические говноделы.
вы по ссылке не способны пройти)? там все есть кроме прокси, а прокси он может быть использован для обратного биндинга, т.е. от меняющихся данных в интерфейс, он тут при том, что для ориентира
Справедливости ради, сделал пример как вы просили. Вот код:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>WC Test</title>
</head>
<script type="module">
class TestElement extends HTMLElement {
  constructor() {
    super();
    this.name = 'John';
    this.secondName = 'Snow';  
    this.attachShadow({
      mode: 'open',
    });
    this.shadowRoot.innerHTML = `
      <style>
        :host {
          display: block;
          color: red;
        }
      </style>
    `;

    const tpl = document.importNode(document.getElementById('tpl'), true);
    
    const nameEl = tpl.content.querySelector('[data-name]'),
        secondNameEl = tpl.content.querySelector('[data-secondName]');

    nameEl && (nameEl.textContent = this.name);
    secondNameEl && (secondNameEl.textContent = this.secondName);

    this.shadowRoot.appendChild(tpl.content);
  }
}
window.customElements.define('test-element', TestElement);
</script>

<body>
  <template id="tpl">
    <span data-name></span> <span data-secondName></span>
  </template>

  <script type="module">
    let startTime = window.performance.now();
    let elemetsTotal = 1000;

    for (let i = 0; i < elemetsTotal; i++) {
      let tEl = document.createElement('test-element');
      document.body.appendChild(tEl);
    }

    window.requestAnimationFrame(() => {
      console.log('Elements total: ' + elemetsTotal + '; Rendering time: ' + (window.performance.now() - startTime) / 1000 + 's');
    });
  </script>
</body>
</html>


Добавил ваш любимый нейтив шаблон приходящий с сервера, убрал лишние мета-теги, даже инсершн данных немного оптимизировал через работу с tpl.content до appendChild.

Ну вот не клеется и все тут:

Rendering time: 0.3287799999816343s
Rendering time: 0.3004850000143051s
Rendering time: 0.28391500003635883s
Rendering time: 0.2724150000140071s
Rendering time: 0.3110449999803677s


Даже до Preact недотянули несмотря на пререндер нативного шаблона, клонирование и отсутствием интерполяции. Нишмогла. Языком чесать все горазды.
может справедливости ради еще финальный отсчет перенести сразу за окончанием цикла, а не когда вам браузер выделит квант рендер-цикла?
у меня если по-вашему показывало 0.14-0.17, а когда перенес 0.04-0.07
вот часть кода которая менялась:
    for (let i = 0; i < elemetsTotal; i++) {
        let tEl = document.createElement('test-element');
        document.body.appendChild(tEl);
    }
    let endTime = (window.performance.now() - startTime) / 1000;

    window.requestAnimationFrame(() => {
        console.log('Elements total: ' + elemetsTotal + '; Rendering time: ' + endTime + 's');
    });
может справедливости ради еще финальный отсчет перенести сразу за окончанием цикла, а не когда вам браузер выделит квант рендер-цикла?

А в чем тут справедливость? Тесты на Preact/Svelte точно также проводились. Только вам нужны какие-то особые условия.

Опять же код самого замера писал не я и использую его как часть ТЗ.
в том что то как вам браузер выделит фрейм зависит от погоды, т.е. вы замеряли что-то другое, может общее состояние операционной системы и процесса, прогретость кешей там
в том что то как вам браузер выделит фрейм зависит от погоды,

Ага, а погода видимо браузеру благоволит стабильно выделять время пораньше для Svelte/Preact, и специально тормозить WC реализацию? Типа такая дискриминация браузером своих же технологий)))

Критиковать и языком чесать все могут. Я взял тест i360u как есть, внес в него те правки, которые вы настаивали дадут мега прерост в скорости. Ничего этого так и не случилось и опять тесты не те. Напишите уже свои кошерные, тогда будем с вашими работать. Не хотите? Тогда может лучше промолчать?
да, по разным причинам перерендер окна может быть вызван позднее, я замерил правильно и получил результат в 3-5 раз быстрее вашего, перезамерьте свои фреймворки, мне уже даже любопытно
Ну если вы так настаиваете…

# WC

Rendering time: 0.2290250000078231s
Rendering time: 0.3163700000150129s
Rendering time: 0.18158500001300126s
Rendering time: 0.34167500003241s
Rendering time: 0.22783999994862825s


# Preact

Rendering time: 0.053139999974519014s
Rendering time: 0.0531300000147894s
Rendering time: 0.038730000029318035s
Rendering time: 0.04254000005312264s
Rendering time: 0.04413499997463077s


# Svelte

Rendering time: 0.01980000000912696s
Rendering time: 0.018329999991692603s
Rendering time: 0.012409999966621399s
Rendering time: 0.018340000067837536s
Rendering time: 0.013339999946765602s


Как видите, относительно друг друга замеры никак не изменились.

Причем, не знаю с чем это связанно, но я только заметил, что если в Svelte версии контент появляется фактически мгновенно, то в версии с веб-компонентами я успеваю заметить как это происходит. Раньше может просто не замечал, но думаю это как-то связанно с переходом на шаблоны вместо innerHTML.

Жду от вас очередной версии того, почему данный тест не корректен. Например, может пример с веб-компонентами было бы справедливо запустить на более мощной машине, а остальные 2 примера на более слабой? Думаю это будет справедливо, а главное возможно уровняет их показатели.
И чтобы уж для совсем полной картины, сделал пример на lit-html. Вот код примера:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Lit Test</title>
</head>
<script type="module">
import { html, render } from 'https://cdn.jsdelivr.net/npm/lit-html@1.0.0/lit-html.min.js';

class TestElement extends HTMLElement {
  constructor() {
    super();

    this.name = 'John';
    this.secondName = 'Snow';
    
    this.attachShadow({
      mode: 'open',
    });
    
    const template = () => html`
        <style>:host { display: block; color: red; }</style>
        <span>${this.name}</span> <span>${this.secondName}</span>
    `;

    render(template(), this.shadowRoot);
  }
}
window.customElements.define('test-element', TestElement);
</script>

<body>
  <script type="module">
    let startTime = window.performance.now();
    let elemetsTotal = 1000;

    for (let i = 0; i < elemetsTotal; i++) {
      let tEl = document.createElement('test-element');
      document.body.appendChild(tEl);
    }

    console.log('Elements total: ' + elemetsTotal + '; Rendering time: ' + (window.performance.now() - startTime) / 1000 + 's');
    
  </script>
</body>

</html>


В результате даже lit-html обогнал использование нейтив шаблонов путем клонирования:

#lit-html

Rendering time: 0.10135500004980713s
Rendering time: 0.10317500005476177s
Rendering time: 0.08349999994970858s
Rendering time: 0.09340999997220933s
Rendering time: 0.11687499994877726s


# WC (template + importNode)

Rendering time: 0.2290250000078231s
Rendering time: 0.3163700000150129s
Rendering time: 0.18158500001300126s
Rendering time: 0.34167500003241s
Rendering time: 0.22783999994862825s


Воттаквот.
на моих замерах где финиш не помещен в ожидание фрейма, веб-компоненты оказались наравне с реакт-дом, но быстрее реакта с редаксом
веб-компоненты оказались наравне с реакт-дом, но быстрее реакта с редаксом

Вполне возможно, но ведь это и прискорбно, потому что реакт очень медленный. Поэтому мы в этом треде с ним и не сравнивали.

Вы сравниваете толстенную рантайм-асбтракцию VDOM c нативной реализаций шаблона и радуетесь тому, что, внимание, начальны рендер на равне с ним? Самому то не смешно? VDOM вообще больше про апдейты, а мы их даже не коснулись тут.

а это был не начальный рендер, а 1000 обновлений, а на начальном вебкомпоненты быстрее раза в 3

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

В наше время быть быстрее реакта — не очень много чести на самом деле. Полагаю, реакт тормознее и Vue и даже Angular. Поэтому мы сравниваем с более релевантными вещами.
да нет все стандартное, для просто реакта там обновляется setState'ом, а для редакса взят стандартный генератор. Я взял реакт, потому что некоторые упирают на его узкозаточенность под производительность. Сейчас уточнил по заметкам, результаты были такие:

Добавляем 1000 элементов на страницу:
WebComponents: ~ 0.05 s
ReactDOM: ~ 0.5 s
т.е. разница на самом деле в 10 раз
Обновляем 1000 раз:
ReactDOM setState(): ~0.38 s
WebComponents .textContent: ~0.37 s
React + Redux: ~2.30 s — утечка памяти оталась (2k обновлений = 500 mb)

bitbucket.org/techminded/js-benchmarks
По ссылке не увидел вашего бенчмарка, только тот, который я публиковал выше. Не знаю, вы реально тугодум или тролите просто, но я вам писал ровно про вот такие вещи:

const tpl = document.importNode(document.getElementById('tpl'), true);

const nameEl = tpl.content.getElementById("firstName"),
  secondNameEl = tpl.content.getElementById("lastName");

nameEl && (nameEl.textContent = this.name);
secondNameEl && (secondNameEl.textContent = this.secondName);

this.shadowRoot.appendChild(tpl.content);


Именно это я и назвал:
у вас используется полностью кастомное решение для апдейта. То есть когда вы знаете конкретные селекторы и делаете все руками.


Противопоставляя это обобщенному подходу state-driven фреймворков, когда вы просто делаете:

this.setState({ ... });

И не паритесь над тем, как конкретно обновить DOM.

да нет все стандартное, для просто реакта там обновляется setState'ом, а для редакса взят стандартный генератор.

То что вы не умеете готовить Реакт уже итак понятно.

Я взял реакт, потому что некоторые упирают на его узкозаточенность под производительность.

На его производительность упирали году так в 2013-14 я думаю. Скорее всего по большей части в сравнении с AngularJS или Backbone. Сейчас Реакт самый популярный, но далеко не самый быстрый уже давно.

Да и вообще, не уверен, что вы в курсе, но vdom вообще ни разу не про скорость.

И еще раз подытожу — сравнивать реакт с веб-компонентами это просто глупо.
да, я использовал ваш код только без ошибки замера, вот вариант как раз с setState

bitbucket.org/techminded/js-benchmarks/src/master/react-state.html

где он проявил себя на равных с обычной работой с dom кстати, не вижу проблемы в том, что-бы сравнить 2 решения по производительности, цель разобраться в том нужны ли все эти замороченные решения в фреймворках, которые якобы решают какие-то проблемы
да, я использовал ваш код только без ошибки замера, вот вариант как раз с setState



не вижу проблемы в том, что-бы сравнить 2 решения по производительности, цель разобраться в том нужны ли все эти замороченные решения в фреймворках, которые якобы решают какие-то проблемы

Фреймворк фреймворку рознь. Замеры выше показывают это. Но даже не смотря на то, что React показал меньшую производительность на вашем тесте, сравнивать его DX с тем, который дает нам использование DOM API просто глупо. Поэтому все ваше сравнение абсолютно не релевантное. Никто в трезвом уме и твердой памяти не будет всерьез сравнивать дикую императивную лапшу на DOM API с лаконичным декларативным описанием компонент на любом из современных фреймворках.

Тем более, если этот фреймворк, такой как Svelte/Preact/LitHtml еще и делает «лапшу» по скорости.

икто в трезвом уме и твердой памяти не будет всерьез сравнивать дикую императивную лапшу на DOM API с лаконичным декларативным


дело в том что альтернативы, т.е. современные фреймворки сделанны дилетантски и противоречат стандартам веб компонентов, браузеров, инженерным практикам. Вот если бы был хороший фреймворк на веб компонентах, тогда это имело бы смысл, а так современное DOM API если довернуть еще хороших решений-библиотек выглядит предпочтительнее сейчас. Насчет тестов вы наверное правы, надо еще сравнить самому с lithtml и svelte%)
дело в том что альтернативы, т.е. современные фреймворки сделанны дилетантски и противоречат стандартам веб компонентов, браузеров, инженерным практикам.

Это мы уже обсуждали, краткий ликбез: 1) вы из мира Java, пришли во фронтенд со своим уставом; 2) большая часть паттернов создавалась тогда, когда не было ни веб, ни таких rich-интерфейсов как сейчас, поэтому один в один они не ложаться на современную разработку; 3) не нравится вам — пишите свой лапшекод.

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

Чем плох тот же StencilJS? Все как вы любите, классы, наследование, декораторы всякие, компиляция.

Насчет тестов вы наверное правы, надо еще сравнить самому с lithtml и svelte%)

Пожалуйста, весь код представлен в треде.
1) вы из мира Java, пришли во фронтенд со своим уставом; 2) большая часть паттернов


я начинал с пхп и питона и много на чем разрабатывал включая js фреймворки, своя особенная специфика была у разработки на js только язык сам по себе был убог, но сейчас в этом нет необходимости и инженерные практики справедливы также и для разработки фронтенда. Хотя я ссылаюсь на них просто что-бы было понятно, что имею ввиду когда вижу в этих велосипедах школячую анскил долбанину, т.е. когда разработчик начинает экономить на буквах или придумывает какое-то «гениальное решение» на хешмапах (обжектах) или заводит обычай раскладывать все по файлам одинаково названным и экспортить с дефолтом

Чем плох тот же StencilJS?


посмотрел и он конечно получше реакта, хотя всеравно заставляет разработчиков инлайнить верстку в джаваскрипт т.е. jsx и непонятно какие задачи он концептуально решает, которые не решены в веб-компонентах, Prop можно самому за несколько часов написать или подключить.
Хотя я ссылаюсь на них просто что-бы было понятно, что имею ввиду когда вижу в этих велосипедах школячую анскил долбанину,

Ну да, ну да… вы свой код то причесали, чтобы кровь из глаз не шла?

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

А вы уверены, что фреймворки этих разработчиков «заставляют»? Не думали, что это требование самих разработчиков?

jsx и непонятно какие задачи он концептуально решает, которые не решены в веб-компонентах,

Вам не понятно, потому что вы не шарите. Также как, я могу сказать, что не понимаю какую проблему решают дженерики в Java и считаю это просто результат плохого дизайна языка.
я помоему даже в этом треде давал пример с прокси, там есть js часть для работы с темплейтом используйте ее
как быть с потенциальными уязвимостями? вдруг кто-нить трояна в килотонны вермишели засунет?

Кто бы говрил про уязвимости и трояны, ну. Прям дежавю с вашим лапшекодом сразу.
админка закрыта на админа, вы стараетесь как можно больше тут навыдумывать?
Не, ну конечно если админка и закрыта, тогда можно на отъ*бись писать код, ага. Только если бы вы юзали не велосипед, а тот же Svelte, у вас бы такого сразу из коробки бы не было. А то заливаете тут про паттерны и колхоз, а как на код ваш взглянули, так слезы на глазах.
чего бы не было)? динамиеческий рендеринг был не работал)? это может быть да конечно… причем тут от*ебись)? это специальная фича, что-бы непрограммисты могли изменять внешний вид и конфигурацию самостоятельно
чего бы не было)?

Не было бы вставки в DOM потенциально небезопасного куска кода без экранизации. Потому что по факту мы сейчас воспроизвели работу над фреймворком/либой. Автор условного фреймворка (это вы) написал говнокод с дыркой, а комьюнити (это я) указало ему на это и он его поправил. Поэтому используя готовое решение, вы априори избавлены от многих забот и проблем. Особенно с вашими подходами к написанию кода.

инамиеческий рендеринг был не работал)? это может быть да конечно

В том то и дело, что работал бы. До кучи лучше, быстрее и с меньшим кол-во говнокода.

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

Вау, вот это вы удивили. Какая уникальная фича в 2019 года. А тупо html получаемый из внешнего источника нельзя что ли перед вставкой в DOM как то санитизировать, не? Не слыхали? А может тогда в прекрасном современном коде на основе XMLHttpRequest сделать какую-то проверочку на хост, откуда тащатся замечательные шаблоны, тоже не за чем? Аднимка же, хоть трава не расти. Главное все с ног до головы в паттернах чтобы было, а безопасность и хороший код — это для колхоза.
дыркой


дырка это когда вы не подозреваете о существовании возможности, а когда для этого все и затевали это уже отверстие

может тогда в прекрасном современном коде на основе XMLHttpRequest сделать какую-то проверочку на хост


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

Вы делали дизамическую подгрузку html с сервера чтобы в нее можно было сделать эксплойт? Не, ну тогда все нормально и вопросов нет. Фича есть фича, сорян.

зачем? хсс для джейсона в современных браузерах не возможен

Так то не зачем, я выше понял что это специальная точка эксплойта. Вы ее видимо как-то эксплуатируете, может заказчикам своим такой код отдаете, а потом данные карт юзеров сливаете. Это как предположение конечно.
Вы делали дизамическую подгрузку html с сервера чтобы в нее можно было сделать эксплойт?

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

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

в другом редакторе задается мапинг его на селекторы, в третьем шаблон

Да, капец как удобно, просто сказка и только. Один вопрос, а для этого реально нельзя сделать санитизацию шаблона перед вставкой в DOM?

Вроде и не сложно даже:

import sanitize from 'sanitize-html';
...
let template = sanitize(settings.template);
...


А, блин, тут же никакой паттерн не прикрутишь, а значит это колхоз по-любому.
Раз выходной файл у Svelte — JS, то считается, так оно работает насколько я знаю везде, просто с разным синтаксисом.

Все так конечно. Способ с разделением на файлы больше про читаемость, когда компонент разрастается.
для не SPA это не проблема, что-бы все необходимые темплейты находились в одном хтмл

Очень интересно, я вот пишу сейчас не особо большие проекты, но даже в тех проектах, которые мы пишем, я не могу себе представить, чтобы мне было удобно так делать. Выглядит как какой-то кастыль очередной.

А что делать с переносимостью компонентов? Например, svelte-компоненты мы свободно используем во многих проектах — взял файлик и скопировал, а внутри все что нужно. Вы как это предлагаете делать?
Очень интересно, я вот пишу сейчас не особо большие проекты, но даже в тех проектах, которые мы пишем, я не могу себе представить,


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

А что делать с переносимостью компонентов?

гораздо лучше, потому что в фреймворке с инлайновыми шаблонами получается прямое связывание лейаута и выковырять кусок компонентами и перенести в другой модуль выходит сложнее
spa это монолит писанный на не самых лучших на сегодня технологиях, огромные заделы разработки в npm присутствуют в виде кривеньких куцых велосипедах как максимум

Набор общих фраз в вашем стиле. Мы например еще и micro-frontends пишем, благо Svelte благоволит этому и что? Как это соответствует тому, что даже там мы не хотим иметь кучу тегом template в серверном шаблоне? На странице может быть сотни компонентов, зачем нам чтобы наш первичный HTML, который скачивает юзер весил тонну? Пусть каждый компонент подгружается динамически с помощью code-splitting и тащит с собой то, что ему нужно.

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

Любой переиспользуемый код можно просто вынести в отдельный модуль и импортировать где угодно.

В вашем же случае, чтобы перенести весь компонент в другой проект, нужно будет скачать отдельно js, css и потом еще не забыл выбрать нужный template-тег из серверного шаблонизатора. Вот уж переносимость.

На странице может быть сотни компонентов, зачем нам чтобы наш первичный HTML, который скачивает юзер весил тонну?


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

В вашем же случае, чтобы перенести весь компонент в другой проект, нужно будет скачать отдельно js, css и потом еще не забыл выбрать нужный template-тег


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

Я же вам четко написал, на одной странице (читай одном пути) может быть несколько десятко и даже сотен компонентов. Наиболее тяжелая часть любого почти компонента — это разметка. Вы предлагаете отказаться полностью от благ динамических импортов и code splitting и отстреливать юзеров мегобайтными html-ами прямо с сервера. Вы хоть читаете, что пишете то?

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

Бывает так, но мы делаем умнее. Если подкомпонент — это просто часто родительского компонента, которая выделяет часть логики/представления для удобства, тогда он лежит в папочке родительского компонента и копируется автоматом с ним. Если же внутри компонента используется какой-то переиспользуемый компонент общего назначения, то его лучше прокинуть через пропсы, чтобы иметь возможность не только не тащить в другой проект, но подменять в динамике:

// Parent.svelte
<svelte:component this={Layout}>
  <Child />
</svelte:component>

<script>
  import Child from './components/Child.svelte'; // относительный путь

  export let Layout = null; // сюда передадим нужный лейаут снаружи при инициализации
</script>


Используем:

<Parent Layout={MainLayout} />

<script>
  import Parent from '~/components/Parent/';
  import MainLayout from '~/layouts/Main';
</script>


Как видите, подкомпонент Child связан с Parent и лежит рядом, а компонент общего плана Layout передается сверху и никак не связан.
как-то слишком много колдовства и прямая линковка, компоненты могут связываться межу собой только эвентами, так устроен html
как-то слишком много колдовства

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

прямая линковка

Прямая линковка тут только между Parent и Child, но это и правильно, потому что Child это не переиспользуемый компонент, а часть Parent, вынесенная в отдельны компонент только для удобства разрабоки.

Parent ничего не знает о том, какой именно компонент будет передан ему в качестве Layout, а значит у них низкая связанность. Об этом знает только компонент, который инициализирует Parent с нужным значением Layout. Это уже рабочий компонент, специфический для конкретного приложения и не предназначенный для переноса в другое место в принципе.

компоненты могут связываться межу собой только эвентами, так устроен html

хм, а как же слоты? что вообще за зашоренный взгляд?
UFO just landed and posted this here
Таких специалистов давно послали нахер со своими мегапаттернами

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

Но самый прикол не в этом, а в том что как ты, блин, будешь использовать веб-компоненты в не-SPA? Типа, создашь огромный HTML, поместишь туда все шаблоны,


веб-компоненты никто не запрещает делать в spa, но с серверными технологиями шаблоны относящиеся к определенному роуту будут во вьюхах серверного шаблонизатора, а общие подключатся и переиспользоваться, настоящая чушь это писать целые приложения и системы со всей бизнес-логикой на жаваскрипте, такие приложения никогда не работают нормально, зато жрут кучу ресурсов и тормозят
UFO just landed and posted this here
То-то ж я пятый год по всему миру катаюсь


ну вот да и шарахать людей по *станам и все говнодельство от этого спроса на эмиграцию

Велком ту кровавый энтерпрайз. За хороших фронтендщиков тут идут настоящие войны


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

У вас просто какая-то своя парадигма мышления. Все эти «заморочи» решаются простой композицией компонентов.

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

А давайте пример?
Все эти «заморочи» решаются простой композицией компонентов.

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

А давайте пример?


пример нескольких querySelector + document.importNode в одном классе вместо return() или import('Something.svelte') вы вообразить просто такое не можете?
А давайте вы не будете заставлять меня изучать экстрасенсорику или следить перепитиями ваших мыслительных процессов, а просто напишете пример такого компонента, а я вам напишу свой в ответ?

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

gitlab.techminded.net/finistmart/com.finistmart.showcase.portlet/blob/master/src/main/webapp/js/showcase-list.js
не знаю зачем вам это надо, когда можно сделать легко самому,

Вы делаете утверждения не подтверденные ничем, кроме вашего бла-бла. Мы же инженеры, как вы сами сказали, а не балаболы. Вот и я вам предлагаю изобразить из себя инженера.

видимо вы хотите воровать

Воровать? А вы в своем уме, уважуемый? Что у вас кто своровал интересно? Мозг если только…

gitlab.techminded.net/finistmart/com.finistmart.showcase.portlet/blob/master/src/main/webapp/js/showcase-list.js

Какой кошмар
зачем тогда такие странные просьбы? вы в самом деле считали что-то это также трудно как реализовать рендер разных лейаутов одним компонентом в фреймворке с инлайном верстки в джаваскрипте?
Я ничего не считаю. Вы, а не я, делаете утверждение, будьте добры подкрепить его фактом, то есть кодом. Остальное это просто набор букв.
Сразу фейл — не могу перенести ваш компонент без того, чтобы разбираться в структуре всего проекта. Где шаблоны?
это пример использования двух шаблонов на не вообще пример для всего, я там писал урывками на выходных, и до причесывания и улучшений можно сказать не дошел, делал сначала что-бы все работало, но в целом он мне нравится больше ваших лохмотьев на фреймворке
А, ну вот, значит я был прав. Java, это видно по стилю вашего общения. У меня со старых времен много знакомых джавистов.

там могут некоторые другие шаблоны браться из конфигурации в админке, будьте осторожны;)

Да, переносимость просто супер. Вместо того, чтобы скопировать один файл и не лазать про проекту. Я должен не только изучить весь проект, но еще и по джавоским шаблонам шарахаться. Так сказать, собирать компонент по крупицам. А если я не шарю, что такое jsp, к примеру? Представим что я обычный фронтендер и даже не представляю где там могут в принципе лежать серверные шаблоны.

в целом он мне нравится больше ваших лохмотьев на фреймворке

Вы же из мира Java, вам должны нравится боль и страдания.))) Геттеры-сеттеры небось пишете? ))) Ну и километровые классы с несколькими уровнями наследования и обязательно интерфейсами. Куда уж без них.
А если я не шарю, что такое jsp, к примеру.

фронтенд-программист это немного оксюморон порожденный казуальностью современных технологий джаваскрипта, тот кто морщится изучить немного нормального обычно проглатывает гораздо больше мусора типа «сторов», «рыдусеров», «геттеров-сеттеров (из вуе), „деструктинга“ и всякого такого. Код как у меня вполне понятен любому обычному программисту, все легко находится в проекте поиском хотя он ориентирован прежде всего на то, что-бы быть управляемым и изменяемым в том числе и из админки, хотя там одна-две вьюхи на весь проект, а другие в других модулях-портлетах и веб-компоненты никак не помешают вам структурировать код как угодно, в отличии от популярных фреймворков кстати

Геттеры-сеттеры небось пишете? )))

среда генерирует, лучше джавы по совокупности практически значимых характеристик ничего за последние 10 лет не было, вот если esnext собрать с вебкопонентами и прочими инжекторами уже ближе, но это только для фронта. Нет во фронтенд разработке кроме селекторов цсс и однопоточности ui ничего прямо особенного относительно бека, поэтому никаких специальных и отличных принципов там не надо.
фронтенд-программист это немного оксюморон порожденный казуальностью современных технологий джаваскрипта

То есть для вас фронтенд — это до сих пор менюшки на jquery открывать/закрывать? Оно и видно. Почему-то мне кажется, что многие с вами не согласятся. Ваш пример наглядно показывает, что бекендер очень часто не может нормально писать и понимать фронтенд. Впрочем как и наоборот.

Код как у меня вполне понятен любому обычному программисту, все легко находится в проекте поиском

Я не говорю, что невозможно найти поиском, вообще зачем? Вот я хочу взять ваш замечательный компонент и перенести в свое приложение, у которого бекенд на php/node/python или даже serverless, что мне делать?

Хорошо, я запарился и нашел ваш серверный шаблон с кучей template'ов. Отфильтровал оттуда несколько штук относящихся именно к тому компоненту, который пытаюсь перенести (что тоже кстати гемор), а дальше вижу:
<template id="${renderResponse.getNamespace()}template-showcase-config">
  <dialog id="${renderResponse.getNamespace()}configDialog" class="my-modal">
  <h3>Settings</h3>
    <div class="fm-form-field">
      <label>Service Url</label>
      <input type="text" name="serviceUrl" value="<%= serviceUrl %>" />
    </div>
    <div class="fm-form-field">
	<label>Or Data</label>
	<textarea name="productData" class="fm-form-text"><%= productData %></textarea>
    </div>
    <div class="fm-form-field">
	<label>Data Mapping</label>
        <textarea name="dataMapping" class="fm-form-text"><%= dataMapping %></textarea>
    </div>
    <div class="fm-form-field">
        <label>Data Template</label>
        <textarea name="template" class="fm-form-text"><%= template %></textarea>
     </div>
     <div class="actions">
         <button id="${renderResponse.getNamespace()}saveDialogBtn" class="small ok-modal-btn">Save</button>
          <button id="${renderResponse.getNamespace()}closeDialogBtn" class="small close-modal-btn">Close</button>
      </div>
  </dialog>
</template>


Получается, чтобы перенести компонент, даже после всего того, что я уже переодалел, мне еще и шаблон переписать придется? Да уж действительно «ориентирован прежде всего на то, что-бы быть управляемым и изменяемым», гы-гы.

лучше джавы по совокупности практически значимых характеристик ничего за последние 10 лет не было

Реальный джавист))))) Узнаю своего знакомого)))

Нет во фронтенд разработке кроме селекторов цсс и однопоточности ui ничего прямо особенного относительно бека, поэтому никаких специальных и отличных принципов там не надо.

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

Узнаю своего знакомого)))


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

банковские интерфейсы «не для людей»

банковские интерфейсы на рякте не очень лучше, а уж с точки зрения разработчиков так и вообще, но вообще это другая немного история, у меня фронтенд составляющая значительно современнее и качественнее чем в типичном таком проекте
конкретно этот код написан не что-бы вам было удобно его куда-то переносить

Какие же это тогда веб-компоненты, если их нельзя переносить? В этом вся соль. К тому же, вы и для переносимости предлагали шаблоны в серверные шаблоны класть, так что сути это не меняет.

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

После C++ мне уже давно ничего не страшно. В Java хоть множественного наследования нет, а мне приходилось в таких дебрях ООП разбираться, что Java по сравнению с этим лайтовый вариант.

банковские интерфейсы на рякте не очень лучше,

Не согласен, все банки которыми пользуюсь перешли с Java-генерируемых админок на нормальные SPA и стали значительно более юзер френдли. В том числе на реакт. То что вы это не вкуриваете, чисто ваша беда.

у меня фронтенд составляющая значительно современнее и качественнее чем в типичном таком проекте

Охотно верю. Послушали, посмотрели.
Какие же это тогда веб-компоненты, если их нельзя переносить?

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

Не согласен, все банки которыми пользуюсь перешли с Java-генерируемых админок на нормальные SPA и стали значительно более юзер френдли

перешли для кого торговля людьми встала во главу угла, что-бы была постоянная текучка и террор сотрудников как в кафешке с официантами

Охотно верю. Послушали, посмотрели.

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

Если бы это был библиотечный код, то вы бы шаблоны для веб-компонентов не поместили в серверные шаблоны, так получается? А где бы они были?

перешли для кого торговля людьми встала во главу угла, что-бы была постоянная текучка и террор сотрудников как в кафешке с официантами

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

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

Эм, вы свой код то видели? Вот этого монстра, котором все в кучу и ничего не понятно. Где сплошное императивное управление DOM. Посмотрев вашу реализацию веб-компонента, я понял что все что видел до этого, было еще очень даже ничего, а уж такие вещи как LitElement и lit-html вообще супер прекрасны, а уважаемый i360u реально спец по веб-компонентам.
Если бы это был библиотечный код, то вы бы шаблоны для веб-компонентов не поместили в серверные шаблоны, так получается? А где бы они были?


положил бы рядом в хтмл, как в ангуляре примерно

В моем окружении ничего такого не наблюдается.


это везде наблюдается, я видел 100ни резюме где опыт работы итшника в одной организации в среднем полгода-год

Эм, вы свой код то видели? Вот этого монстра, котором все в кучу и ничего не понятно.

что-то вы завираетесь, там не больше 300 строчек кода на файл, конечно с провокаторских подколупок было бы странно что-то еще ожидать:)
положил бы рядом в хтмл, как в ангуляре примерно

А как бы вы его подключили в js файл с описанием компонента?

это везде наблюдается, я видел 100ни резюме где опыт работы итшника в одной организации в среднем полгода-год

1-2 года это вообще стандарт работы в одной организации, ничего в этом страшного нет. Я же писал, про какой-то там террор сотрудников, видимо с вами такое бывало.

что-то вы завираетесь, там не больше 300 строчек кода на файл,

300 строк js кода, без шаблона и стилей — это просто гигансткий компонент. Его уже минимум 3 раза нужно было разбить для части.
>> А как бы вы его подключили в js файл с описанием компонента?

document.write + getElementById например?

>> 1-2 года это вообще стандарт работы в одной организации

т.е. за 30 лет стажа неофициант должен поменять 15-30 нетеррористов? не удивительно что каждый год все переписывается новыми одаренными

300 строк js кода, без шаблона и стилей — это просто гигансткий компонент


для меня это ориентир просто, я разделял по смыслу, необходимости дробить на компоненты там где смысл не требует что-бы удобнее было тыркать стейты как в рякте тут нет, когда посчитаю нужным вынесу все как надо будет
document.write + getElementById например?

Вы написали, что у вас будет лежать рядом js файл с классом компонента и тут же файл html c шаблоном. Вопрос, как вы импортируете html шаблон в файл с js классом?

т.е. за 30 лет стажа неофициант должен поменять 15-30 нетеррористов?

В ИТ да, текучка большая, особено тех, кто хочет развиваться быстро. Со временем оно конечно утихает, но в целом это нормально. На первом месте я проработал 2 года, а последнем уже больше 5-ти.

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


Вы функции таким же принципом пишете? Если функция с одним смыслом, то пусть будет хоть 1000 строк и быть совершенно не читаемой, так?

На самом деле вы так пишете, потому что веб-компоненты не дают удобно разделять логику на компоненты и обмениваться данными между ними. Если бы вы сделали ваш код удобным для чтения, разделив его на несколько компонентов то столкнулись бы слишними проблемами их коммуникации. Это как если бы фукнции вашего ЯП не умели нормально принимать и возвращать параметры, а в классах не было бы контекста. Также и в веб-компонентах, коммуникация между ними сложна и неочевидна, аттрибуты только строки, а все компоненты регистрируются в глобальном реестре.
Вопрос, как вы импортируете html шаблон в файл с js классом?

можно реализовать метод лоадер, примерно как импорт в вашем фреймворке или лоадеры systemjs/webpack, до недавнего времени все лоадеры в джаваскрипте были построены либо на заворачивании в анонимки и инлайн в жс либо на script.src = url && document.write

Вы функции таким же принципом пишете? Если функция с одним смыслом, то пусть будет хоть 1000 строк и быть совершенно не читаемой, так?

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

я вам 3 раза или более повторил что это непродуктовый код, который пока писался что-бы работало в условиях дефицита времени на это. Проблемы коммуникации решаются гораздо проще чем в популярных и не очень фреймворках, у меня есть код с гораздо большим количеством компонетов и вообще всего, который я вам по NDA показать никак не могу. Коммуникация между веб-компонентами происходит через эвенты и это гораздо понятнее всяких выдуманных стор систем, у меня в том коде кстати есть примеры коммуникации с другим модулем.
можно реализовать метод лоадер, примерно как импорт в вашем фреймворке или лоадеры systemjs/webpack, до недавнего времени все лоадеры в джаваскрипте были построены либо на заворачивании в анонимки и инлайн в жс либо на script.src = url && document.write


Куда же делась ваша приверженность всему нативному? А еще пререндеру шаблона и все такое))))) Как только сталкиваешься с задачами реального мира, сразу начинаются велосипеды. Лучше уж тогда взять инструмент, где все это уже есть и работает на ура.

функция должна влазить в экран, это один из критериев быстрой оценки

Ваш компонент на экран не влазит, при том что там даже не весь компонент, а только его скрипт. С шаблонами и стилями будет еще в 2 раза больше. Или у компонентов какая-то другая оценка?

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

Вы мне его и не показывайте, напишите небольшой пример, который показывает принцип. А то с NDA это стандартная отмазка, знаете ли. И чем это интересно это проще чем во фреймворках? Например, в Svelte точно также события на компонентах и точно такие же метода на их инстансе, но кроме того есть еще биндинги настоящие, включая 2way. То есть все что можно реализовать на веб-компонентах, можно и там и даже больше.

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

О, видел тут недавно на митапе. Коммуникацию веб-компонентов через ивенты. Там компоненты стреляли ивентами, внутри detail передавая свой собственный инстанс, чтобы компонент-получатель мог через него что-то сделать с компонентом продуцирующим ивент. Адсткая императивная жесть. Я бы посмотрел на ваш вариант.
Вдруг он действительно так хорош, тогда я мог бы просто взять и использовать его в Svelte.
Лучше уж тогда взять инструмент, где все это уже есть и работает на ура.

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

Ваш компонент на экран не влазит, при том что там даже не весь компонент,

мой компонент не функция, а класс если все правильно попиленно, а не намешанно в вермишель, в этом не трудно ориенироваться в среде разработки или редакторе

И чем это интересно это проще чем во фреймворках? Например, в Svelte точно также события на компонентах и точно

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

То есть все что можно реализовать на веб-компонентах, можно и там и даже больше.

еще один казуальный фреймворк не поддерживающий стандарты и паттерны вобщем-то просто не нужен, если вам удастся изучить технологий 5-10 вы поймете, насколько ценно их качество, а не какие-то особенные штучки
О, видел тут недавно на митапе. Коммуникацию веб-компонентов через ивенты. Там компоненты стреляли ивентами, внутри detail передавая свой собственный инстанс, чтобы компонент-получатель мог через него что-то сделать с компонентом продуцирующим ивент.

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

Похоже у вас javaголовногомозга. Никакие паттерны вам не напишут хороший код. Более того, давно уже изветсно, что зачастую разработчики сконцентрированные на паттернах слишком ими злоупотребляют. Вся Java это сплошной пример концепции ООП бездумно возведенной в абсолют. Испльзование паттернов и даже стандранов ниразу не характеризует качество кода, которое можно реализовать на основе технологии.

мой компонент не функция, а класс если все правильно попиленно, а не намешанно в вермишель, в этом не трудно ориенироваться в среде разработки или редакторе

И что? То есть по-вашему классы могут быть хоть 10К строк? У вас как раз все намешано мама не горюй. Вермишель с лашпой и рисом сверху. Чего стоит только вот этот прекрасный кусок:

buy(event, data) {
  this.addToCart(event, data);
  document.addEventListener('cart-list:rendered', (event) => {
    document.dispatchEvent(new CustomEvent('cart-list:showdelivery', { bubbles: false }));
  });
  document.dispatchEvent(new CustomEvent('cart:show', { bubbles: false }));
}


Мало того, что компонент ShowcaseList слушает и продуцирует ивенты с префиксами cart: и cart-list:, так еще и на каждый вызов метода buy будет создаваться новый лисенер на документ. И никто это все лисенеры не удалит, когда веб-компонент будет удален из DOM.

Лично я не увидел в вашему коде ни одного паттерна и даже просто удачного решения.

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

Обобщение мать всех ошибок. А учитывая как вы код пишете, я бы про кривость и школоло промолчал бы лучше. К тому же Svelte 3 просто использует CustomEvent с небольшой оберткой над ним, чтобы не писать бойлерплейт код.

еще один казуальный фреймворк не поддерживающий стандарты и паттерны вобщем-то просто не нужен, если вам удастся изучить технологий 5-10 вы поймете, насколько ценно их качество, а не какие-то особенные штучки

Ваше понятие о «качестве» мы уже посмотрели. Спасибо, такого качества ненадо. К тому же, как я уже писал по треду, Svelte компирируется в веб-компоненты одним флагом и на 100% поддерживает текущий стандарт. Так что вы просто говорите о том, о чем не знаете.

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

Правильнее вообще не дергать императивно инстансы и методы других компонентов ни напрямую, ни через сервис. Все это лишнее связывание. Если уж работаем с ивентами, это должен быть event-driven стиль в чистом виде.
К тому же Svelte 3 просто использует CustomEvent с небольшой оберткой над ним, чтобы не писать бойлерплейт код.


бойлерплейт это фреймворки не по стандартам и паттернам, а бинд эвента переделать это не проблема, вы же предлагаете говоря языком аналогий из-за опечатки, использовать китайский. В том коде может не много паттернов, но и антипаттернов не так много
Даже не знаю, что вам ответить. Для программирования это как бы нормально вынести повторяющийся код в функцию и использовать ее и для удобства и для сокращения кода.

В каком месте тут не стандарты и не паттерны, я ума не приложу. Это совершенно естественный процесс для разработки, но видимо вы у на сособенный. Перепишем ваш «код для избранных»:

    addToCart(event, data) {
        document.dispatchEvent(new CustomEvent('cart:additem', { bubbles: true, detail: { item: data }}));
    }

    buy(event, data) {
        this.addToCart(event, data);
        document.addEventListener('cart-list:rendered', (event) => {
            document.dispatchEvent(new CustomEvent('cart-list:showdelivery', { bubbles: false }));
        });
        document.dispatchEvent(new CustomEvent('cart:show', { bubbles: false }));

    }


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

function dispatch(name, options) {
  document.dispatchEvent(new CustomEvent(name, options));
}
...

addToCart(event, item) {
  dispatch('cart:additem', { 
    bubbles: true, 
    detail: { item } 
  });
}

buy(event, data) {
  this.addToCart(event, data);

  document.addEventListener('cart-list:rendered', e => dispatch('cart-list:showdelivery'));

   dispatch('cart:show');
}
не понял зачем эта обертка над диспатчем?
не понял зачем эта обертка над диспатчем?

Мне иногда кажется что вы просто троль. Но объективно причин этому может быть несколько:

  1. Это повторяющийся код, который вы используете как минимум в 3-х местах одного только этого компонента. Собственная это классичекая причина выделить что-то в функцию.
  2. Далее, это практически ничего не значащий по отдельности бойлерплейт код, который решает одну задачу — даспатчинг ивента, а значит может быть представлен функцией решающей эту задачу.
  3. Такой вариант будет весить меньше, особенно если вынести это в общие хелперы для всех компонентов. Если ваше приложение содержит 100 компонентов, каждый из которых по 3 раза использует эту конструкци, то написав ее один раз в виде функции вы сможете бесплатно сэкономить лишние байты.
  4. Если в процессе работы над приложением, вам например понадобиться логировать все диспатчи ивентов или даже выставить брейкпоинт просто, внести еще какое-то изменение в этот шаблонный процесс, вы легко сможете это сделать в одном месте, а не бегая по всем местам использования
  5. Мы знаем, что по умолчанию, CustomEvent не баблится, а нам например нужно, чтобы наши ивенты баблились в 90% случаев, то логичнее один раз прописать это в функции, а баблинг отключать в тех местах где нужно.
  6. И наконец это просто более читаемо и удобно в использовании


Раз вы так любите паттерны, но почему то тут вы за WET, а не DRY.
этот код я легко причешу до совсем конфетного состояния, а вы из своей свельты или еще какого казуального ужаса нормального кода не сделаете переписав все с 0
этот код я легко причешу до совсем конфетного состояния, а вы из своей свельты или еще какого казуального ужаса нормального кода не сделаете переписав все с 0

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

У вас какие критерии?
по стилистике кода колхоз как в свельте, вуе или рякте не проходит сразу, ангуляр чуть пограмотнее, критерии все описаны в любой книжке про паттерны и практики программирования на нормальных языках программирования, например прочитайте про SOLID, они отработаны с годами практики и решения различных задач и проблем, пренебрежение ими всегда чревато проблемами с развитием и поддержкой продукта, а следование с умеренным фанатизмом позволяет получить код, с которым не больно работать и через 10к лет
по стилистике кода колхоз как в свельте, вуе или рякте не проходит сразу

Это ваше субективное мнение. Для кого-то ООП стиль написания такой же колхоз. Я же предлагаю более объективные критерии оценки кода.

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

Опа, стандартная отмазка про SOLID. Вы у себя в коде его давно видели, не? Уверен, что ваш код по критерию SOLID я точно смогу побить.

с которым не больно работать и через 10к лет

С вашим кодом больно работать с первого взгляда. Уж простите. И я не уверен, что вам под силу сделать его не то чтобы SOLID, но просто читаемым и поддерживаемым.
собственно кроме неймспейса там ничего страшного нет, вы дуете слона на ровном месте
а есть еще немного динамического контента, это сильная сторона веб-компонентов, что можно все динамически рендерить как нативное, во фреймворках тройки такое непросто и непрямо достигается
если скопипастить этот код не убирая теги серверного шаблонизатора тоже кстати ничего ужасного не произойдет%) я думаю все даже будет работать это будет просто строки, а вот ваши фреймворки бы сломались
теги вашего svelte такие же синтаксически грязные кстати и выковырять переиспользовать их в ангуляр не получится принципиально) надо будет все все переписувать, поэтому я вцелом за чистый Native Templates без надстроек и альтернатив
а есть еще немного динамического контента, это сильная сторона веб-компонентов, что можно все динамически рендерить как нативное, во фреймворках тройки такое непросто и непрямо достигается

Веб-компоненты не могут быть отрендерены на сервере без эмуляции DOM или Headless Chrome и это их большой минус. Динамический контент и на сервере и на клиенте должен браться из Апи, чтобы все работало изоморфно. А вы предлагаете его рендерить на сервере в помощью серверных шаблонов, а на клиенте брать из апи, так что ли?

теги вашего svelte такие же синтаксически грязные кстати и выковырять переиспользовать их в ангуляр не получится принципиально)

Да, только Svelte я просто возьму и запущу на сервере как есть и он мне просто выдаст готовую html-ку для отправки юзеру. И не придется мне еще и серверные шаблоны клепать

>> Веб-компоненты не могут быть отрендерены на сервере без эмуляции DOM или Headless Chrome

шаблоны это пре рендер, а рендер вызывающий конструкторы и колбеки, вы легко напишете сами хоть на жс

Да, только Svelte я просто возьму и запущу на сервере как есть и он мне просто выдаст готовую html-ку для отправки юзеру. И не придется мне еще и серверные шаблоны клепать


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

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

В Svelte я могу просто взять любой компонент и отрендерить его на сервере в строку, сколь бы сложным он не был и сколько бы компонентов внутри не содержал. Это и есть SSR, а не то что вы пишете.
В Svelte я могу просто взять любой компонент и отрендерить его на сервере в строку, сколь бы сложным он не был и сколько бы компонентов внутри не содержал.


круто, но это не оправдывает казуальщины, кроме того это может означать, что рендерит он все-таки через вставку строк в dom. Что-бы отрендерить веб компонент думаю восновном достаточно вызвать конструктор класса и connectedCallback.
круто, но это не оправдывает казуальщины,

Не знаю что вы имеете ввиду здесь.

кроме того это может означать, что рендерит он все-таки через вставку строк в dom.

Нет, это просто означает что это компилятор и он может компилить одни и те же мои компоненты в разные таргеты. Для фронта он компилируется либо в class либо в custom element, а для сервера в строку. В будущем может даже в нативную мобилку сможет.

Что-бы отрендерить веб компонент думаю восновном достаточно вызвать конструктор класса и connectedCallback.

Серьезно? А ShadowDOM мы куда денем? А на сервере у вас document/window есть? Как будете нейтив шаблоны клонировать?
Не знаю что вы имеете ввиду здесь.

странные неочевидные для разработчика решения, какая-то особенная магия
а для сервера в строку.

в строку для сервера как раз будет native template, а большего не надо, сервер лучше загрузит js'ы из отдельных файлов, потому что это будет специальный отдельный сервер на проде

Серьезно? А ShadowDOM мы куда денем? А на сервере у вас document/window есть?


это жи жс — все можно наполифиллить своими нахлобучками, поддержки шедоудом для ие11 нет, а полифилл есть, значит можно сделать свой для рендера в строку
странные неочевидные для разработчика решения, какая-то особенная магия

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

в строку для сервера как раз будет native template, а большего не надо, сервер лучше загрузит js'ы из отдельных файлов, потому что это будет специальный отдельный сервер на проде

Да чтоже это такое то? Вы вообще не ферштейн? Вот у вас веб-компонент:

class MyComponent extends HTMLElement {
     constructor() {
           super();
           const tpl = document.createElement('template');
           const { foo, bar } = this.attributes;
           tpl.innerHTML = `
                 <div>${foo}</div>
                 <div>${bar}</div>
           `;
           this.appendChild(document.importNode(tpl.content, true));
     }
}

customElements.define('my-component', MyComponent);


Вот мы его используем:

   <my-component foo="Hello" bar="world"></my-component>


Ваша задача с сервера вернуть не просто пустой тег веб компонента, а с его содержимым и контентом, примерно так:

   <my-component foo="Hello" bar="world">
       <div>Hello</div>
        <div>world</div>
   </my-component>


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

Ок, я вас понял, вопросов больше к вам нет. Единственное замечание, в IE11 хоть и нет shadowdom, но там есть весь остальной DOM. И нахлабучивать вам придется весь DOM, как я и написал выше — либо эмуляция DOM на сервере, либо Headless Chrome. И то и то, вам и вашим юзерам по скорости рендерига не понравится.
реализуйте методы document, реализуйте генератор инстанциирующий классы элементов и все дела, наверняка кто-то такое уже сделал
реализуйте методы document, реализуйте генератор инстанциирующий классы элементов и все дела, наверняка кто-то такое уже сделал

Конечно делал, это и называется эмуляция dom. Работает она правда сложнее, чем вам наивно представляется, а главное работает ооочень медленно, по сравнению с нормальным SSR и в прод вы это не захотите.
SSR для веб-компонентов не нужен, как и склейка в бандлы кроме отдельных библиотек не нужна для современной модульности и HTTP/2

// ладно у нас тут уже ночь, я — спать
Причём тут склейка в бандлы и SSR? Что вы несёте. Реально, вам бы проспаться.
выковырять переиспользовать их в ангуляр не получится принципиально

Пропустил про ангуляр. Вы так и не поняли фишку — в ангуляр мы будем переиспользовать не шабоны, а полностью готовый Svelte компонент. Просто возьмем его и засунем в приложение на Ангуляр, точно также как я это сделал вот в этой статье для Реакта. Почему? Да потому что Svelte — это чистая ванила.
ни с какого бока оно на ванилу не похожа, наоборот — полно казуальщины, например антипатерн export default, причем обжектов, странные аттрибуты у тегов все там странно, как в рякте и вуе, но немного по-другому конечно. В этих кульбитах нет необходимости в разработке.
<button on:click="$set({ clicked: true })">click me</button>

похоже на перл в тегах
Вы реально тупите или просто троль? Вы ведь из Java и по идее должны понимать что такое компилятор, да? Я вам тыщу раз давал ссылки на статьи и просто писал, что Svelte — это компилятор. Вы же не думаете, что то что вы пишете на Java прям так запускается на виртуальной машине? Или думаете?

Вот это код:

<button on:click="$set({ clicked: true })">click me</button>

Компилируется в совершенно ванильный:

const button = document.createElement('button');
button.textContent = 'click me'; 
button.addEventListener('click', () => {
  $store.set({ clicked: true });
});


После компиляции Svelte компонент — это ванильный JS класс без внешних зависимостей, который можно просто взять и использовать где угодно, а не только в ангуляре. Ферштейн или для вас это сложно?
это лишние атрибуты которые вам придется восстанавливать, при обновлениях дизайна, ладно бы это было еще в жс коде отдельно от верстке, а не шаблоне
это лишние атрибуты которые вам придется восстанавливать, при обновлениях дизайна, ладно бы это было еще в жс коде отдельно от верстке, а не шаблоне


Каком еще обновлении дизайна? Когда у вас произойдет обновление дизайна, а в js коде идет выборка по селектору, которого в шаблоне больше нет, вам не придется ничего делать, не?

Очень понравился вот этот ваш кусок, простоя высшая степень «хороших паттернов»:

let template = settings.template;
...
let itemContainer = document.createElement('div');
...
itemContainer.insertAdjacentHTML('beforeend', template);
let mappings = settings.dataMapping || [];
for (let mapping of mappings) {
  let el = itemContainer.querySelector(mapping.sl);
  if (mapping.valType && mapping.valType === 'style' && mapping.valTmpl) {
    el.style = mapping.valTmpl.replace('%%', jsonPath(product, mapping.valExp));
  } else {
    if (el !== null) {
      el.textContent = jsonPath(product, mapping.valExp);
    }
  }
}


Для тех, кто не в курсе, settings приходит с сервера.)))) То есть мы не только получаем с сервера неизвестный кусок html и вставляем его в DOM внутри веб-компонента, но оттуда же получаем список каких-то маппингов, и потом по неизвестному селектору, который описан в этих маппингах, мы изменяем этот html, пришедший с сервера, добавляя стили.

WAT? Это типа у вас такое понятие об инкапсуляции и правильной работе с DOM? Это у вас такое представление о читаемом коде? Я даже представить не могу, что я в итоге должен увидеть в DOM, читая это код. Более того, получается у нас веб-компонент завязан на сервер не только своим стейтом, но и еще разметкой. Вот так SOLID и паттерны там всякие.
там можно задать данные, мапинги и шаблоны отображения прямо в админке, все без лазания в код, это такая типа фича, я ведь уже 4 раза повторял, что повторял про назначение этого кода?
там можно задать данные, мапинги и шаблоны отображения прямо в админке, все без лазания в код, это такая типа фича, я ведь уже 4 раза повторял, что повторял про назначение этого кода?

Это повод писать кривой и небезопасный код что ли? Вы так про это говорите, как будто это rocket science какой-то. REPL у Svelte устроен сложнее, чем у вас. Он на любом изменеие кода все пересобирает автоматом и обновляет вьюху прямо на клиенте. И вообще, вы просто не понимаете, но нет никакой проблемы сделать то, что делаете вы ни на одном фреймворке.
Каком еще обновлении дизайна? Когда у вас произойдет обновление дизайна, а в js коде идет выборка по селектору, которого в шаблоне больше нет, вам не придется ничего делать, не?

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

А вам типа не придется? У вас дизайны видимо будут меняться консистентно с лапше-кодом, которых располагается в разных местах и завязан на разные куски DOM/шаблонов. Знаем мы это все, проходили с Jquery. Это значительно сложнее рефакторится потом.

Когда у тебя небольшой декларативный компонент в одном файле рефакторить его в разы проще, и не нужно куда-то бегать по файловой системе, искать вызовы document.querySelector или el.addEventListener. У вас видимо не много опыта с фронтендом, раз вы не знаете об этих проблемах.

Более того, так как компонент Svelte — это фактически валидный html файл (в v2 даже кастомное разрешение .svelte не используется, а просто .html). Дизайнерам и верстальщикам очень нравится с этим работать. У нас в компании, js программисты и верстальщики часто разные люди. Очень классно, когда верстальщик может просто отдать готовый компонент вида:

<ul>
  <li>
     <img>
     <h6>title</h6>
     <input type="checkbox">
  </li>
</ul>
<button>Buy selected</button>

<style>
  ul { ... }
  ul li { ... }
  button { ... }
  ...
</style>

А js программист просто туда натянет логику и поведение и моментально получит что-то вроде:

<ul>
  {#each products as { title, id, img }}
  <li>
     <img src={img}>
     <h6>{title}</h6>
     <input 
       bind:group={checked} 
       value={id} 
       type="checkbox"
     >
  </li>
  {/each}
</ul>
<button on:click={e => addToCart(checked)}>
  Buy selected
</button>

<script>
  import { addToCart } from './cart.js';

  export let products = [], checked = [];
</script>

<style>
  ul { ... }
  ul li { ... }
  button { ... }
  ...
</style>

Если для вас плюсы такого подхода с точки зрения того же редизайна не ясны, то это лишь говорит о ваших компетенциях и опыте во фронтенде (ваш серверный опыт я не оцениваю никак)
Блин, а вот это вообще генеально, а главное супер паттерн, смотрите хакаем ваш код:

1) открываем консольку пишем:
const showcase = document.createElement('showcase-list');
showcase.setAttribute('settingsUrl', 'https://evilserver.com');
document.body.appendChild(showcase);


2) что происходит дальше — наш супер SOLID-паттерный код написанный по всем стандартам делает запрос на чужой веб-сервер, чтобы загрузить settings:

    loadSettings() {
        return new Promise((resolve, reject) => {
            let xhr = new XMLHttpRequest();
            xhr.open("GET", this.settingsUrl);
....


3) а после спокойно отрисовывает пришедщий оттуда html код с любым вредоностным js кодом:

let template = settings.template; // пришло с evil сервера
...
itemContainer.insertAdjacentHTML('beforeend', template); // отрисовали в DOM "как есть" через insertAdjacentHTML


Читаем Security considerations:
When inserting HTML into a page by using insertAdjacentHTML(), be careful not to use user input that hasn't been escaped.


Ооочень надеюсь, что вы не в банковской сфере работаете…
Готов потратить еще пару минут и на примере Hello world, как для студентов, объяснить как это работает:

Мы пишем декларативный, хорошо читаемый компонент, на высоком уровне абстракции

<h1>Hello {name}</h1>

<script>
  export let name = '';
</script>

<style>
  h1 { color: red; } <!-- стили сразу инкапсулированы -->
</style>


Далее, он компилируется в ванилу, статически анализируются все связи между представлением и стейтом компонента и генерируется ванильный класс, который мы можем использовать из любого внешнего js кода:

import HelloWorld from './HelloWorld.svelte';

const hw = new HelloWorld({
   target: document.body,
   props: { name: 'world' }
}); // отрисует 'Hello world' в document.body 

hw.name = 'syncro'; // обновит dom на 'Hello syncro'


Внутри ванильного класса, будет ванильный DOM API с небольшим кол-вом хелперов для уменьшения бойлерплейта. Все, очень просто, декларативно, очевидно и читаемо.
Я уже писал автору статьи, что его тест некорректен от слова совсем, напишу и вам: в одном случае создаются компоненты, в другом — заполняется шаблон одного компонента/контейнера. То есть аналогичный код на WC будет выглядеть как-то так:
    class FilledElement extends HTMLElement {
      constructor() {
        super();
        this.name = 'John';
        this.secondName = 'Snow';
        this.attachShadow({
          mode: 'open',
        });
        let html = /*html*/ `
          <style>
            :host {
              display: block;
              color: red;
            }
          </style>
        `;
        for (let i = 0; i < 1000; i++) {
          html += `<div>${this.name}</span> <span>${this.secondName}</div>`;
        }     
        this.shadowRoot.innerHTML = html;
      }
    }
    window.customElements.define('filled-element', FilledElement);

Сравните теперь скорость (у меня где-то 14ms). Не стоит раз за разом сравнивать теплое с мягким, если хотите сравнить скорость рендера тысячи переиспользуемых компонентов с собственными свойствами — то и сравнивайте именно их. Речь вообще изначально шла о том, что некорректно скорость веб-компонентов замерять на LitElement, и я написал почему. Хотите адекватный тест? Сравните сравнимое: чистые компоненты, LitElement, React и Vue.
Я уже писал автору статьи, что его тест некорректен от слова совсем, напишу и вам: в одном случае создаются компоненты, в другом — заполняется шаблон одного компонента/контейнера.

Во-первых, это чисто ваш тест, я лишь портировал его на Svelte. Во-вторых, у меня 2 компонента: Test.svelte и App.svelte. Перебор массива происходит вне компонента Test.svelte, то результата работы скрипта — это 1000 компонентов Test на странице.

То есть аналогичный код на WC будет выглядеть как-то так:

Это не так. Вы засунули цикл в один компонент и пробежались массивом внутри него. То есть результат работы вашего скрипта — это один компонент с 1000-й div-элементов внутри. По вашему это аналогично?

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


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

# Файл Test.svelte — внимание, отдельный компонент!
<div>
  <span>{name}</span> <span>{secondName}</span>
</div>

<script>
  let name = 'John', secondName = 'Snow';
</script>

<style>
  div { display: block; color: red; }
</style>

# Файл App.svelte — внимание, отдельный компонент!
{#each Array.apply(null, { length }) as _}
<Test /> <!-- вот тут мы в цикле создаем length-компонентов Test -->
{/each}

<script>
  import Test from './Test.svelte';
  export let length = 0;
</script>

# Файл main.js — внимание, отдельный файл!
import App from './App.svelte';

const startTime = window.performance.now(),
  length = 1000;

const app = new App({
  target: document.body,
  props: { length }
});

window.requestAnimationFrame(() => {
  console.log(`
    Elements total: ${length}; 
    Rendering time: ${(window.performance.now() - startTime) / 1000}s
  `);
});

export default app;


Более того, в вашем примере всего 1 компонент (TestElement), а в моем примере компонента 2 (Test и App), что по-идее должно быть даже менее производительным. Код файла main.js практически соответствует вашему второму script тегу, кроме того, что создание 1000 компонентов Test происходит не внутри обычно js-цикла, а с помощью инструментов доступных в Svelte. Собственно именно так такой код и пишется и я не вижу причин, почему это не соответствует вашему примеру.

Эти компоненты не только переиспользуемые, они до кучи полностью инкапсулированные, включая стили (именно поэтому я спокойно юзаю просто имя тега div для стилей и не боюсь что все теги div станут красными), и даже разбиты на отдельные файлы. Компонент Test понятия не имеет кто и сколько раз нарисует его на странице.

Хотите адекватный тест? Сравните сравнимое: чистые компоненты, LitElement, React и Vue.

Не очень понял, почему эти 4 варианта сравнимы, а варианты на Preact и Svelte нет?
Preact — сравним сам по себе, но тест написан некорректно. Svettle — вообще нет ибо время замеряется не верно. Повторю в сотый раз, что речь шла о особенностях рендера LitElement, поэтому и начинать сравнивать нужно с него в первую очередь. Остальное — по вкусу.
Чтож, вот вам еще пример. Тут что по-вашему некорректно и замеряется неверно?
то, что вы за стартовое принимаете время после компиляции. То есть, по сути, выкидываете из теста всю механику работы с шаблоном. Шедеврально.
И что? Так работает Svelte. Шаблоны существуют только до момента сборки, а дальше все это дело превращается в обычные вызовы DOM API.

Более того, сравнение со Svelte даже более корректное, чем с Preac/React и любым другим VDOM решением, именно потому что Svelte в рантайме не использует все эти тяжелые абстракции, так же как и ваш ванильный код.

Ведь получается, что у меня на выходе js класс и вызовы DOM API и у вас тоже js класс и вызовы DOM API. И при этом мой код работает быстрее, почему? Ответ очевиден — из-за веб-компонентов, которые вы используете, а я нет.

А то, что с таким-же успехом можно сравнивать рендеринг компонентов со статичным html-шаблоном (или результатом работы любого PHP-шаблонизатора). То, что вы не учитываете инициализацию шаблона с добавлением в него начальных данных, вы просто рендерите готовый html-код. Да, именно так работает Svetle, и именно поэтому его некорректно сравнивать с фреймворками, которые я привожу в пример. В этом подходе есть как плюсы так и свои минусы, обсуждение которых выходит за рамки текущей дискуссии. Я никак не могу понять, вы больше надо мной издеваетесь или над здравым смыслом? Может вам перечитать ветку сначала, чтобы понять, что тащить сюда Svetle для сравнения, не было никакого смысла? Речь шла о разнице между скоростью нативного парсинга HTML и первичного парсинга в JS-рантайме, реализованного в LitElement. Причем тут Svetle? Может он поддерживает инкапсуляцию стилей? Может компоненты на Svetle я могу использовать в проекте на React или Angular? Может он не требует никаких собственных зависимостей и поддерживает нативный синтаксис?
А то, что с таким-же успехом можно сравнивать рендеринг компонентов со статичным html-шаблоном (или результатом работы любого PHP-шаблонизатора). То, что вы не учитываете инициализацию шаблона с добавлением в него начальных данных, вы просто рендерите готовый html-код.

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

Я вам вот тут написал примерный код, который генерит Svelte. Ладно текст не читаете, но код то можете надеюсь?

В каком тут месте рендеринг готового html шаблона в момент компиляции? Именно это по вашему делает document.createElement? Вы уверены, что вообще видели DOM API? Какой еще к черту PHP?

export default class Test {
   constructor({ target }) {
       const div = document.createElement('div');

       /* другие вызовы DOM API */

       target.appendChild(div);
   }
}


Я вам черным по белому пишу — Svelte на этапе компиляции превращает компоненты в ванильный JS класс, внутри которого делаются прямые вызову к DOM API. Что вам тут непонятного? Какие еще шаблоны, строки, статический html, вот это все вы откуда взяли? Сами придумали?

Более того, Svelte абсолютно реактивный. Это мы сейчас с вами чисто вывод сравнивали, а когда пойдут апдейты в DOM, с веб-компонентами вообще потонешь.

Может вам перечитать ветку сначала, чтобы понять, что тащить сюда Svetle для сравнения, не было никакого смысла? Речь шла о разнице между скоростью нативного парсинга HTML и первичного парсинга в JS-рантайме, реализованного в LitElement. Причем тут Svetle?


Svelte туда я затащил, потому что уже было добавлено сравнение с Preact и мне стало интересно. Не вижу никаких причин, чтобы этого не сделать. Пример ваш собственный, чего вы боитесь то? Раз веб-компоненты такой супер-крутой натив и очень быстрый, то они должны в хлам рвать любой фреймворк, разве нет? Смысл сравнивать чистую реализацию с надстройкой над ней же? Ежу понятно, что любая надстройка, созданная для удобства разработчика, будет налагать издержки на изначальную реализацию. Поэтому это не корректое сравнение в корне. А вот сравнить реализацию с веб-компонентами, без веб-компонетов (Svelte) и с VDOM (Preact), это уже интересно.

Может он поддерживает инкапсуляцию стилей?

Да, поддерживает, без shadow dom и даже там, где его вообще нет.

Может компоненты на Svetle я могу использовать в проекте на React или Angular?

Именно так, на выходе ванильный js без зависимостей. Вот
статья на хабре.

Может он не требует никаких собственных зависимостей и поддерживает нативный синтаксис?

Верно, никаких зависимостей. Чтобы любой компонент Svelte скомпелировать в custom element, нужно всего лишь выставить флаг customElement: true. Поддержка стандарта 100%, вот пруф:
custom-elements-everywhere.com/libraries/svelte/results/results.html

Вы может выберетесь из своих собственных фантазий и взгляните на мир со стороны?

Понятно, вот здесь возникли разночтения. Изначальная идея теста была в том, что мы создаем переиспользуемый веб-компонент (что-то вроде Card из material design) и рендерим их в списке (назовем его CardsList). В случае веб-компонентов Card и CardsList сливаются вместе ради производительности. Либо удобство разработки либо скорость, надо выбрать что-то одно.


В случае Preact/Svelte/другого фреймворка накладные расходы на создание переиспользуемого компонента меньше, поэтому выйдет и удобно, и производительно.

Ничего никуда не сливается в случае, если вы хотите переиспользовать Card.
В случае Preact/Svelte/другого фреймворка накладные расходы на создание переиспользуемого компонента меньше, поэтому выйдет и удобно, и производительно.

с чего такой вывод?
А чем рендеринг Card в цикле будет отличаться от рендеринга TestElement?
Решил переписать свой пример, так чтобы вам было понятнее, что это одно и тоже:

# Файл Test.svelte — Ваш аналог TestElement
<div>
  <span>{name}</span> <span>{secondName}</span>
</div>

<script>
  let name = 'John', secondName = 'Snow';
</script>

<style>
  div { display: block; color: red; }
</style>


# Файл main.js — Ваш аналог второго тега script
import Test from './Test.svelte';

const startTime = window.performance.now(),
  length = 1000;

for (let i = 0; i < length; i++) {
  new Test({ target: document.body });
}

window.requestAnimationFrame(() => {
  console.log(`
    Elements total: ${length}; 
    Rendering time: ${(window.performance.now() - startTime) / 1000}s
  `);
});

Отличия лишь в том, что чтобы поместить компонент Test на страницу я вызываю конструктор компонента, а вы его создаете с помощью createElement. Внутри конструктора делается все тот же target.appendChid()

Ну и что вы думаете? Вот результаты:

# Svelte
Rendering time: 0.12290499999653548s
Rendering time: 0.11193000001367182s
Rendering time: 0.10559000005014241s
Rendering time: 0.12220999994315207s
Rendering time: 0.10138999996706843s

Как и ожидалось стало чуть быстрее, потому что исчез дополнительный компонент App.svelte, но не принципиально, потому что он был слишком мал. Кроме того, размер доставляемого js кода также уменьшился до 2.8Kb.

Так что, спасибо вам за замечание, теперь все еще очевиднее стало.

ох… не подскажете что это такое у вас с расширением *.svelte? Как оно в браузер попало? А еще не подскажете, почему этот фреймворк называют «магически изчезающим»?
Вы бы хоть для приличия изучили то, о чем вам другие люди говорят. Вроде все тут специалисты со стажем. Ну уж ладно, раз для вас гугл закрыт, расскажу:

не подскажете что это такое у вас с расширением *.svelte?

.svelte — это формат Single File Components специфичный для фреймворка SvelteJS, который дает возможность удобно и декларативно описывать переиспользуемые компоненты (включая стили). Примерно такой же подход используется в таких фреймворках как Vue, Ractive, Riot. Даже Angular и React стараются все инкапсулировать в один файл, который удобно переиспользовать в разных проектах.

Как оно в браузер попало? А еще не подскажете, почему этот фреймворк называют «магически изчезающим»?

Особенность фреймворка Svelte в том, что по-факту это компилятор SFC в ванильные классы без зависимостей. В итоге в браузер попадает просто js код.

В данной реализации я не использую веб-компоненты и custom elements. Но Svelte имеет возможность один флагом скомпилировать любой компонент в custom element, но этим почти никто не пользуется в данный момент, по причинам описанным в данной статье.
Вы бы хоть для приличия изучили то, о чем вам другие люди говорят.

боже, это был сарказм. О должен был вам намекнуть почему сравнение некорректно. Но вижу это бесполезно.
боже, это был сарказм.

Сложно понять когда вы серьезно, а когда просто недогоняете о чем пишете.
О должен был вам намекнуть почему сравнение некорректно.

Сравнение более чем корректно, по причинам описанным тут.

Хорошо, давайте тогда забудем о Svelte. Ведь он «исчезает» в рантайме. У меня есть просто js файл компонента (не важно откуда я его взял, написал сам или мне его Svelte сгенерил), который экспортирует JS класс, а внутри делает вызовы в DOM API:

export default class Test {
   constructor({ target }) {
       const div = document.createElement('div');
       
       /* другие вызовы DOM API */

       target.appendChild(div);
   }
}


И дальше я его использую так:

for (let i = 0; i < 1000; i++) {
  new Test({ target: document.body });
}


Чем это принципиально отличается от вашего класса:

class TestElement extends HTMLElement {
  constructor() {
    super();
    this.name = 'John';
    this.secondName = 'Snow';
    this.attachShadow({
      mode: 'open',
    });
    this.shadowRoot.innerHTML = `
      <style>
        :host {
          display: block;
          color: red;
        }
      </style>
      <span>${this.name}</span> <span>${this.secondName}</span>
    `;
  }
}


И вашего использования:

for (let i = 0; i < 1000; i++) {
  let tEl = document.createElement('test-element');
  document.body.appendChild(tEl);
}


Кроме как тем, что вы ипользуете веб-компонента, а я нет?
Вы начинаете задавать правильные вопросы, но почему-то отвечать вам уже не очень хочется. Я в последний раз потрачу на это свое время, далее — умываю руки.

Итак, как это явно читается в коде, создавая Custom Element, вы расширяете нативный браузерный элемент и создаете для его дальнейшего использования свой отдельный тег. В структуре HTML-дерева, данный тег может иметь собственных родителей и потомков, которые ведут себя так-же, как элементы внутри и снаружи любого другого тега. Все те-же связи класса родитель-потомок и методы DOM API доступны в обычном режиме. На этом этапе, это практически ничем не отличается от вашего примера, кроме, собственно, появления нового типа тегов. Используя такой тег вместо обычного SPAN вы никакой практически разницы в скорости его отрисовки не увидете. На этом сходство кончается. Далее, вы хотите большего, и пытаетесь добавить в свой новый элемент собственные свойства, логику и структуру, независимые от родителей и потомков текущего узла в DOM-дереве. Конечно, вы можете просто усложнить общую структуру документа, добавив все необходимое, и даже автоматизировать этот процесс (как делает Svetle), но в этом случае вы значительно усложняете отношения класса родитель-потомок в рамках структуры компонентов. Это не большая проблема, если вы не планируете особых манипуляций с получившимся DOM-деревом. Но делая что-то более сложное, типа онлайн-редакторов, вы начинаете потихоньку огребать от эффектов увеличившейся сложности. Вы получаете «прозрачную» структуру: взаимно влияющие друг на друга стили и прочие сайд-эффекты с поднятием событий и пр. Теперь вам требуется быть очень внимательным с тем, что ваш компонент наследует сам, и что передает своим потомкам, то есть получаете ту самую «помойку в глобальном скоупе» против которой вы выступали, но уже на разных уровнях абстракций, где ее сложнее контролировать. Ваш компонент не имеет как такового разделения на собственную внутреннюю структуру и то, что он содержит как композиционная абстракция. Чтобы решить эту проблему, придумали Shadow DOM. По сути, это специальный узел, который добавляет в вашу разметку дополнительное измерение, позволяя выделить все необходимое в отдельный загон, оставив родителей и потомков на своих местах. Его добавление, конечно, несет дополнительные издержки, но не особенно превышающие издержки усложнения структуры. Более того, у вас появляется дополнительная возможность влиять на структурирование потомков в виде именованных слотов (вы можете, к прмеру, завернуть ВЕСЬ лейаут типовой страницы в такой тег и пулять его из серверного шаблонизатора как обычный html, содержимое которого будет индексироваться поисковиками как на статической странице). А польза от возможности инкапсулировать стили уже значительная. Поскольку шаблоны компонентов описываются внутри js-строк, вам также становится доступна всякая дополнительная магия, типа CSS-миксинов (которая в нативном виде будет поддерживаться еще неизвестно когда) и выражений, которые гораздо мощнее нативных calc(), attr() и счетчиков. Ну и препроцессоров конечно, поскольку в отличие от них вам доступна реакция на изменения в рантайме. Однако, добавление дополнительной ноды собственных стилей в каждый компонент также несет издержки, и замедляет первичную отрисовку. Фокус тут лишь в том, что оптимизация данного процесса становится доступна на уровне браузерного движка, со всеми его хардкорными возможностями типа кэширования всяческих предикшенов и т. д. Кроме того, при создании шаблона компонентов вовсе не обязательно каждый раз парсить html, можно клонировать ноды из тега template, что является дополнительной возможной оптимизацией (я именно так и делаю). В итоге, мы получаем набор плюсов и минусов, которые взвешиваем и принимаем решение о том юзать нам это все или нет. В моей практике, плюсов на порядок больше, и к тем инструментам декомпозиции, которые я использовал ранее, после веб-компонентов мне не хочется. Если вас больше устраивает Svetle — на здоровье, это хорошая штука.
UFO just landed and posted this here
Тут проблема скорее не в перерисовке, т.к. браузер сам способен определить диффы и применить только изменившиеся свойства в стилях документа, а в парсинге нового содержимого самого style. Лучше такой ситуации, конечно, не допускать и в рантайме пробрасывать изменения непосредственно к целевым элементам, через CSS-переменные например. Миксины могут содержать эти переменные, но сами миксины желательно однократно отработать при первичном парсинге шаблона.

Попробуйте CSS-переменные. В стилях у вас будут не конкретные значения а переменные, которые можно определить через JS. Вот пример:
https://jsfiddle.net/c6bph70k/ Цвет текста задается динамически, через переменную, обновлять CSS не нужно.


Если интересно, можете еще посмотреть на StyleSheet API. Это что-то вроде DOM API, только для работы со стилями.

UFO just landed and posted this here
Я в последний раз потрачу на это свое время, далее — умываю руки.

Красиво начали, но далее уныло рассказали очевидное. А главное, так и не ответили на вопрос — почему вы считаете что пример на веб-компонентах и на Svelte нельзя сравнивать?

В итоге имеем, что там и там js класс и прямые манипуляции в DOM. Так что делаю вывод, что примеры вполне себе сравнимы и очевидно веб-компоненты почти в 2 раза менее производительны. Печаль.

Это не большая проблема, если вы не планируете особых манипуляций с получившимся DOM-деревом. Но делая что-то более сложное, типа онлайн-редакторов, вы начинаете потихоньку огребать от эффектов увеличившейся сложности.

С чего вы это все взяли? Svelte прекрасно справляется с любыми манипуляциями в DOM и делает их максимально эффективно. Впрочем как и практически все JS фреймворки. А что здесь нам предлагают веб-компоненты? По сути ничего, только императивный DOM API, который не умеет ни change detection, ни иных форм определения что изменилось и что надо поменять.

Вы получаете «прозрачную» структуру: взаимно влияющие друг на друга стили и прочие сайд-эффекты с поднятием событий и пр.

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

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

Компоненты Svelte не имеют наследования, только композицию.

Ваш компонент не имеет как такового разделения на собственную внутреннюю структуру и то, что он содержит как композиционная абстракция.

Несмотря на то, что в итоге все находится в общем DOM, так как внесение изменений в DOM происходит только через механизмы Svelte, то со стороны разработчика компоненты имеют четкую, инкапсулированную внутреннюю структуру. Если же, к примеру, нужно прикрутить стороннее решение, которое хочет манипулировать каким-то DOM элементом мимо фреймворка (Jquery плагин например), это делается с помощью специального механизма экшенов — по сути life-cycle для DOM элемента. Пишется простая обертка над тем же jquery плагином, которая всего лишь функция. Очень быстро и удобно.

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

Это правда, что только Shadow DOM дает полную реальную инкапсуляцию всего и вся, но зачастую это и не нужно. Более того, часто это приводит к лишним сложностям архитектурного плана.

Более того, у вас появляется дополнительная возможность влиять на структурирование потомков в виде именованных слотов (вы можете, к прмеру, завернуть ВЕСЬ лейаут типовой страницы в такой тег и пулять его из серверного шаблонизатора как обычный html, содержимое которого будет индексироваться поисковиками как на статической странице).

В Svelte есть точно такие же именнованные слоты. Однако кроме этого, Svelte может сделать реальный SSR своими силами прямо на сервере, а не через фоллбек на стороне серверных шаблонов. То есть вам не придется писать дополнительный серверный код, чтобы сгенерить тот же html, который уже создается в ваших компонентах. Вообще SSR одна из самых слабых частей веб-компонентов, поэтому давайте не будет об этом.

А польза от возможности инкапсулировать стили уже значительная.

Инкапсуляция стилей есть, писал уже не раз. Делается она конечно не с помощью Shadow DOM, но работает хорошо. Я бы даже сказал лучше, потому что в отличии от веб-компонетов все стили можно в итоге собрать в единый CSS-файл, сохраняя инкапсуляцию.

Поскольку шаблоны компонентов описываются внутри js-строк, вам также становится доступна всякая дополнительная магия, типа CSS-миксинов (которая в нативном виде будет поддерживаться еще неизвестно когда) и выражений, которые гораздо мощнее нативных calc(), attr() и счетчиков. Ну и препроцессоров конечно, поскольку в отличие от них вам доступна реакция на изменения в рантайме.

Динамические стили давно обсуждаются в сообществе Svelte. В целом реализация их проста и возможна, но пока пришли в выводу, что копирование стилей для каждого инстанса компонента — это слишком затратно. В примере выше, нам пришлось бы сгенерировать 1000 style тегов компонента Test, чтобы иметь возможность пробрасывать туда куски стейта в динамике. А излишняя динамика может сильно сказаться на производительности. Поэтому в Svelte мы используем динамику внутри аттрибута style элемента, причем делается это по умному, точечно изменяя свойства, к примеру:

<div style="width: {width}px; height: {height}px;"></div>


Здесь, если будет изменено только проперти {width}, весь аттрибут style не будет пересобран. Будет сделано прямо изменение в соответствующее css свойство. height останется не тронутым, несмотря на то, что визуально это выглядит как простая интерполяция.

Второй вариант — CSS переменные. Причем, в веб-компонентах все тоже самое, давайте не будет вводить в заблуждение. Проблемы ровно такие же и злоупотреблять с этим все равно не получится.

В общем, как я понял продолжать дискуссию по поводу сравнения вы не намерены, ваше право. Я в свою очередь, считаю что провел сравнение максимально корректно и само сравнение вполне возможно в таком виде, так как реализации в целом соответствуют друг другу. Цифры есть цифры, ничего зазорного в этом нет, несмотря на то, что они так и не подтвердили ваши заявления. Ведь в итоге, главное чтобы вам нравилось и ваш DX был на высоте.

Лично я такого в веб-компонентах не заметил. Блин, да они даже property reflection не поддерживают, как все html элементы. Все руками.
UFO just landed and posted this here
Тут, к сожалению, все далеко не так радужно, как хотелось бы и могло бы быть. (((

— про change detection — есть attributeChangedCallback

Во-первых, сначала стоит взглянуть на синтаксис:
attributeChangedCallback(name, oldValue, newValue){}

Думаю очевидно, что эта штука очень быстро превращается либо в безумный switch-case, либо обрастает очередной оберткой. Во-вторых, этот коллбек не поддерживает bunch-апдейты, то есть функция будет вызвана столько раз, сколько аттрибутов изменится. Это усложняет задачи когда, например, нужно сделать что-то при изменении нескольких аттрибутов. Какой уж там DX.

К примеру, в Svelte 2 подобная вещь сделана так:
onstate({ current, previous, changed }){
  /* current - весь актуальный стейт */
  /* previous - весь предыдущий стейт */
  /* changed - измененный стейт */
}


Но это даже не самое прискорбное. Дело в том, что веб-компоненты не поддерживают property reflection, как это делают остальные html элементы. Вот например:

const div = document.createElement('div');
div.setAttribute('id', 1);
document.body.appendChild(div);
div.id // "1"
div.id = 2; // 2
div.getAttribute('id') // "2"


Логично? Вроде бы да (есть конечно проблема с приведением типов, но хотя бы значение верное), но не для веб-компонентов:

class MyComponent extends HTMLElement {
  constructor() {
     super();
     this.foo = 1;
  }

  static get observedAttributes() { return ['foo']; }

  attributeChangedCallback(name, oldValue, newValue) { 
    console.log('attribute changed', name, oldValue, newValue);
  }
}
customElements.define('my-component', MyComponent);

const comp = document.createElement('my-component');
comp.setAttribute('foo', 2); // attribute changed foo null 2
document.body.appendChild(comp);

comp.foo; // 1
comp.foo = 3; // 3 , а где attributeChangedCallback ?
comp.getAttribute('foo') // "2", а точно, это же веб-компоненты


Обратите отдельное внимание, что attributeChangedCallback был вызван лишь один раз.

О каком DX тут вообще может идти речь? Даже такую вроде как очевидную вещь как property reflection приходится делать в полностью ручном режиме:

class MyComponent extends HTMLElement {
  constructor() {
     super();
     this.foo = 1; // NUMBER
  }

 /* и так для КАЖДОГО проперти */
 get foo() {
    return +this.getAttribute('foo'); // STRING to NUMBER
 }

 set foo(val) { // STRING
    this.setAttribute('foo', +val); // STRING to NUMBER
 }
 ...
}


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

Еще вариант — использовать обертки типа LitElement, то есть по-сути фреймворки.

— DX — это сильная сторона веб компонентов, потому что как минимум в dev-режиме работаешь именно с тем кодом, который попадает в браузер. С нашлепками типа lit-element или Polymer код все равно остается практически тем же, что мы правим в IDE, без всякого build step-а


Не уверен, что после предыдущего пункта вы все еще думаете, что DX и веб-компоненты можно использовать в одном предложении. И все же, есть же source-map'ы и HMR.

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

Самое прекрасное в стандарте веб-компонентов — это идея, лежащая в их основе. Жаль реализация этой идеи не оправдывает ожиданий.
UFO just landed and posted this here
Этот пункт был замечанием на «DOM API, который не умеет ни change detection...». Поэтому я уточнил, что все же имеет.

Я тут наверное недостаточно полно написал, но в изначальном комментарии имел ввиду конечно не только само определение изменений, но и в целом синхронизацию стейта и DOM. И attributeChangedCallback это лишь малая часть работы. Поэтому и существует lit-html.

Из коробки не умеют, но я из коробки и не пользуюсь.

И правильно делаете, но есть господа, которые утверждают, что из коробки все прекрасно и замечательно. Все так и должно быть. Видимо вы тоже так не считаете.

Source Maps совсем не требуются — это лишнее место где что-то может поломаться, здесь такого места нет. Как и в случае с HMR. Я, кстати, не вижу препятствий для его технической реализации для веб-компонентов. Ну и, следовательно, мне пересборку не приходится запускать совсем.

Согласен, что хорошо когда лишних инструментов нет. Я лишь отметил, что в целом эти проблемы уже решены. Сама по себе сборка все равно нужна, вы же в итоге минифицируете и склеиваете наверное код.

Кроме того, в случае с такими умными штуками как Svelte, сама по себе компиляция несет сразу много плюшек. Например, никакой веб-компонент не подскажет вам, что в вашем компоненте есть неиспользуемые css правила и заботливо не вырежет их из итогового кода. А Svelte это сделает. А главное работает это все практически мгновенно.

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

Тут вы приложение по факту уже загрузили ведь, то есть на клиент уже пришел файл с классом компонента и где-то он был задефайнен.

Вот как этот же код мог бы выглядеть на Svelte (если работать с компонентами отдельно, как у вас):

authenticate()
  .then(() => import('./App.svelte'))
  .catch(e => {
    console.error(e);
    return import('./Login.svelte');
  })
  .then(({ default: Component }) => {
     new Component({ target: document.body });
  });


Только с настоящей динамической подгрузкой. Вроде бы тоже довольно просто.

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

Не могу не согласиться. Сам принципиально не работаю с очень большими проектами. Нудятина та еще.

UFO just landed and posted this here
Вот как этот же код мог бы выглядеть на Svelte (если работать с компонентами отдельно, как у вас):


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

То есть вы не в курсе что такое динамические импорты да? Если вы читаете этот простейший код и не сразу понимаете, тогда о чем вы можем вообще говорить?
О каком DX тут вообще может идти речь? Даже такую вроде как очевидную вещь как property reflection приходится делать в полностью ручном режиме:


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

Да, только я не зря привел пример с property reflection для нативных html элементов. Когда я создаю кастомый html элемент, я, как минимум, ожидаю похожего поведения. Но вы видимо уже привыкли и не видите в этом ничего странного. Если вам это нравится и удобно — дело ваше. Я считаю что это бред.
сейчас в веб-компонентах даже обновляемые аттрибуты надо перечислять явно, это совершенно разные по особенностям поведения сущности с пропертями класса
Так это и плохо все. О чем и пишу я, автор статьи и еще дофигище человек. Базовое поведение кастомных элементов должно быть похожим на встроенные. Все эти несостыковки и определяют негативное отношение к ним.
никогда не ощущал этой разницы, негативное отношение или скорее вообще отсутствие знания про веб-компоненты определила агрессивная популяризация фреймворков навроде реакта, затем вуе. Кроме того полимер и другие фреймворки на веб-компонентах, нельзя сказать что-бы тоже удачно состряпанные, мне он тоже не понравился. А вот когда я собрал веб-компоненты на современных стандартах джаваскрипта с инжектором и роутером, тогда получилось хорошо и удобно
И просто для сравнения, как это работает в Svelte 3:

// MyComponent.svelte

<script>
  let foo = 1, 
      bar = 2; // private property

  export {
    foo // public property
  };
</script>


// используем из js

import MyComponent from './MyComponent.svelte';

const comp = new MyComponent({
  target: document.body,
  props: { foo: 2 }
});

comp.foo; // 2
comp.foo = 3; // 3 + ререндер html


// используем из другого компонента

<MyComponent foo={2} />

<script>
  import MyComponent from './MyComponent.svelte';
</script>

UFO just landed and posted this here
На самом деле я ничего не имею против lit-element и lit-html. Суть всего спора был в том, что они появились не от хорошей жизни, а потому что веб-компоненты в чистом виде использовать крайне сложно и неудобно.

А раз так, то это уже нельзя назвать «встроенной в браузер технологией» или «разработка на чистой ваниле» или «мы работаем без фреймворка». Все же 6.6Кb gz+min которые весит Lit-Element — это вполне себе размер легковестного фреймворка. Тот же Preact весит меньше.
UFO just landed and posted this here
С веб-компонентами нет никаких особых проблем ни с контролем зависимостей (реестр компонентов дает вам всю необходимую информацию о том, что вы регистрируете в рантайме в любое время)

Ну да, а когда 15+ лет назад все складывали в window тоже можно было сказать, что есть единый реестр и можно в любой момент получить информацию. Только вот что-то практика показала, что любой глобальный объект или реестр ничего хорошего не несет.

вы можете производить инъекции максимально эффективно через старый добрый DOM API.

Старый да, но добрый ли? И для кого это и когда DOM API был добрым? По мне так это дикая, плохо стандартизированная до сих пор, жутко императивная и не удобная штука. Ни разу не видел, чтобы на сколь-либо крупном проекте использование чистого DOM API несло добро.

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

Вот тут сложно не согласиться.
Ну да, а когда 15+ лет назад все складывали в window тоже можно было сказать, что есть единый реестр и можно в любой момент получить информацию. Только вот что-то практика показала, что любой глобальный объект или реестр ничего хорошего не несет.


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

Старый да, но добрый ли? И для кого это и когда DOM API был добрым? По мне так это дикая, плохо стандартизированная до сих пор, жутко императивная и не удобная штука. Ни разу не видел, чтобы на сколь-либо крупном проекте использование чистого DOM API несло добро.


В всех UI-фреймворках используется DOM API. Это какбэ единственный способ взаимодействия с DOM, доступный из js-рантайма. Или это все недостаточно крупные проекты? Я правильно понимаю, innerHTML, textContent и селекторы — это ужасно сложно и нестандартизированно?
Есть разница между помойкой в глобальном скоупе и упорядоченным реестром со своими методами. А еще синглтон — это антипаттерн у хипстеров, угу.

Чем глобальный скоуп кастом-элементов так сильно отличается от глобального скоупа в виде window? Разве он как-то исключает коллизию имен? Разве если я попробую зарегистрировать компонент с уже существующем именем он не даст мне это сделать, перезаписав существующий, или хоть как-то сообщит об этом? Может быть там внутри есть какой-то поиск, который позволил бы мне в произвольном месте узнать имя нужного мне компонента, если, к примеру, имена динамические? По большому счету это ровно такая же помойка с ровно теми же проблемами.

Я правильно понимаю, innerHTML, textContent и селекторы — это ужасно сложно и нестандартизированно?

Тем, кто работает с этими фреймвоками в 99% случаев не требуется взаимодействовать с DOM API никаким образом. Лично мне, как разработчику фронтенда, а не разработчику фреймворка, хочется работать с гараздо более высокоуровневым апи, чем DOM API. Грязную работу я вполне готов делегировать фреймворку.

Разве если я попробую зарегистрировать компонент с уже существующем именем он не даст мне это сделать, перезаписав существующий, или хоть как-то сообщит об этом? Может быть там внутри есть какой-то поиск, который позволил бы мне в произвольном месте узнать имя нужного мне компонента, если, к примеру, имена динамические?

Именно. Иногда стоит глянуть на доки прежде чем комментировать.
Тем, кто работает с этими фреймвоками в 99% случаев не требуется взаимодействовать с DOM API никаким образом.

Еще неплохо следить за контекстом того, на что отвечаете. Я писал о подходе реализованном в LitElement, если я не ошибаюсь. Тем не менее, если фронтендер не владеет основами работы с DOM (а в большинстве случаев ничего сложнее основ и не требуется), на мой взгляд, ему не место в профессии.
Именно. Иногда стоит глянуть на доки прежде чем комментировать.

Что именно? В первым пунктом сплоховал, да, выдаст исключение. Недавно смотрел доклад, там походу докладчик сам спутал. Но это по большому счету ничего не меняет. Только то, что это не произойдет в тихую. Используя window мы тоже всегда проверяли наличие ключа и можно было кинуть исключение, но проблемы при этом все еще оставались.

Еще неплохо следить за контекстом того, на что отвечаете. Я писал о подходе реализованном в LitElement, если я не ошибаюсь.

Нет, вы писали что мол в веб-компонентах никаких прослоек не нужно, можно все через DOM API. Вопрос, почему именно в веб-компонентах не нужно, а в фреймворках нужно? В вашем высказывании явно указано, что когда мы пишем на веб-компонентах, тогда лучше юзать DOM API. Я и написал, что я как разработчик не хочу использовать низкоуровневые апи в задачах, связанных с разработкой продуктов. Что касается Lit-Element, полагаю что они использовали lit-html потому что это их же разработка, внутри которой DOM API используется напрямую. Зачем им еще раз писать тоже самое в lit-element не очень понятно.

Тем не менее, если фронтендер не владеет основами работы с DOM (а в большинстве случаев ничего сложнее основ и не требуется), на мой взгляд, ему не место в профессии.

Дело не во владении, а в удобстве разработки и как это влияет на скорость разработки проектов и качетво кода. Реализовывать каждый раз то, что уже сделано во фреймворках, имхо, не очень продуктивно и судя по мейнстриму, так считаю не только я.

Я и написал, что я как разработчик не хочу использовать низкоуровневые апи в задачах, связанных с разработкой продуктов. Что касается Lit-Element, полагаю что они использовали lit-html потому что это их же разработка, внутри которой DOM API используется напрямую. Зачем им еще раз писать тоже самое в lit-element не очень понятно.


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

Это все меняет. Вы не хотели коллизий? Вы их не получите. Вы хотите реализовать проверку? Пожалуйста. В чем пробле то? developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry
Нет, вы писали что мол в веб-компонентах никаких прослоек не нужно, можно все через DOM API.

Согласен, мой косяк, я сам перепутал ветки. Но вопроса выдергивания из контекста это не отменяет. Я вроде как уже миллион раз повторил что не стоит противопоставлять веб-компоненты фреймворкам (и я этого не делаю), и не только в комментариях к данной статье, но вы упорно записываете это в мне во грехи. Успокойтесь уже, никто вас не заставляет писать на голых компонентах (хотя это иногда и имеет смысл для производительности).
В чем пробле то?

Проблема в том, что если один 3rd-party элемент `calendar-popup` юзает внутри кастомный элемент `date-select` и другой 3rd-party элемент `datetime-chooser` юзает внутри элемент с таким же именем `date-select`, то при установке этих двух элементов к себе в приложения я неизбежно получу исключение. Соответственно мне либо придется изучать внутреннюю структуру веб-компонентов, чтобы понять могут ли они конфликтовать, либо править в чужие компоненты. Ни то, ни другое меня не прельщает. По-моему это довольно очевидная проблема, которая автоматически порождается глобальным скоупом, даже таким «умным» как реестр.

Успокойтесь уже, никто вас не заставляет писать на голых компонентах (хотя это иногда и имеет смысл для производительности).

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


вы получите исключение при попытке использовать другой класс для того же тегнейма, при этом вы всегда можете добавить проверку на то определен ли уже такой тегнейм, т.е. это как раз не проблема использование глобального скоупа, а решение проблемы в виде ограничения, без которого могли бы возникать коллизии использования тега разными компонентами
Все так, но вы видимо не поняли проблему. У меня вот есть приложение и я качаю с гитхаба 2 веб-компонента и вставляю их себе на страницу:

....
<script src="./components/calendar-popup.js"></script>
<script src="./components/datetime-chooser.js"></script>
....
<calendar-popup></calendar-popup>
....
<datetime-chooser></datetime-chooser>


Захожу посмотреть как они классно работают, а вместо этого вижу в консольке:

VM82:1 Uncaught DOMException: Failed to execute 'define' on 'CustomElementRegistry': this name has already been used with this registry


Как так, думаю я, имена то разные у меня везде. Но оказывается что Вася, который делал calendar-popup и Джордж, который делал datetime-chooser для внутренних нужд этих компонентов сделали ряд внутренних компонентов (ну там, чтобы логику разделить, код переиспользовать и все такое прочее), и назвали, а главное задефайнили эти компоненты одинаково:

// Вася код
class DateSelect extends HTMLElement {}
customElements.define('date-select', DateSelect);

// Джордж код
class DtSelect extends HTMLElement {}
customElements.define('date-select', DtSelect);


Чем в такой ситуации мне поможет это исключение или проверка? Тут мы конечно вспомним про всякие там соглашения и префиксы, только многолетняя практика показывает, что никакие соглашения не спасают от таких ситуаций.
дело в том, что вася и джорж не должны были делать дейфайн там же где объявлен код компонентов, т.к. это как раз таки означает использовать глобал в своих кодах или как-то еще безусловно хардкодить конфигурацию. Хотя им скорее всего показалось проще и быстрее делать именно так, как и делать верстку прямо в жс коде.

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

Джордж задефайнил компонент date-select чтобы использовать его внутри компонента datetime-chooser, другого способа использовать веб-компонент не определено стандартом. Пользовательский код компонента datetime-chooser вообще не должен знать что внутри есть какой-то там date-select, потому что это означает вникать в детали реализации.

Сбутстрапить компоненты наинжектив им заодно зависимостей должен был некоторый общий код, какой-то аналог DI фреймворка

Во-первых, вы опять доказали, что сами по себе, веб-компоненты практически недееспособны, раз чтобы заюзать парочку компонентов нужно сверху крутить DI.

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

Во-вторых, вы утверждаете, что в Angular нельзя просто взять 3rd-party компонент и заиспользовать его, без ручного управления всему его зависимостями через DI? Вы уверены в этом? Потому что в моем примере речь именно об этом — компонент date-select не используется нигде кроме как внутри компонента datetime-chooser.

Внешний код вообще не должен знать о его существовании и это легко реализуется на любом современном фреймворке просто по средставам es6 модулей. Не нужно никаких DI, если только вы не хотите мокать/свапать компоненты для тестов или подобных нужд.

Вобщем это та часть технологии, которая отдается на откуп фреймворкам и библиотекам я думаю.

Да, наверное это так, но в случае с веб-компонентами, система их регистрации делает практически невозможным реализацию подобной вещи, без участия конечного пользовательского кода. Можно наверное генерировать какие-то префиксы/постфиксы силами фреймворка, но это выглядит больше как хак, чем здравое решение.

Джордж задефайнил компонент date-select чтобы использовать его внутри компонента datetime-chooser, другого способа использовать веб-компонент не определено стандартом.


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

Во-первых, вы опять доказали, что сами по себе, веб-компоненты практически недееспособны, раз чтобы заюзать парочку компонентов нужно сверху крутить DI


крутить или не крутить решают разработчики ферймворка, вот вам не нравится — вы не крутите, а тот кто понимает зачем это и имеет опыт — прикрутит

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


так и где тут проблема? зато с участием можно сделать как угодно: я знаю минимум 2 способа несложно сделать это самому, есть готовые библиотеки-инжекторы, есть те или иные решения во фреймворках. В конце концов вы действительно можете решить, что вам хватит одних компонентов или глобальной персистанс системы типа редакса. Веб компоненты это набор технологий-стандартов, а не фреймворк и не библиотека.
что-бы использовать одни элементы в других нет необходимости дефайнить их в строго определенном порядке, в этом крутизна веб-компонентов, что пока вы не задефайнили кастомный элемент браузер его просто пометил как неизвестный и пропустил

Даже не знаю, что тут комментировать. Спасибо капитан, все так. Только какое отношение это имеет к описанной проблеме? Я разве писал вам, что если компонент не будет задефайнен его нельзя поместить в разметку?

так и где тут проблема?

вы дествительно не видите разницы между тем, чтобы просто взять и использовать 3rd-party компонент и тем, когда вам сперва нужно изучить все его зависимости, каким-то образом заинджектить/задефайнить их, чтобы имена не конфликтовали с абсолютно всеми компонентами вашего приложения. Нет?

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

зато с участием можно сделать как угодно: я знаю минимум 2 способа несложно сделать это самому, есть готовые библиотеки-инжекторы

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


вы писали что его надо дефайнить прямо сразу в том же жс выдав себя за боба;)

не будет задефайнен его нельзя поместить в разметку?


абсолютного решения этой проблемы без побочных эффектов не существует, используя другие компонентные ферймворки можно сделать что-то вроде статической сборки, но в этом случае у вас не будет модульности, а будет монолит, а это никому, кроме джунов вчера увидевших впервые рякт, не нужно. Все понимают, что любой вася может собрать хеловорлд СПА на рякте, вы сделайте что-бы у вас безконфликтно на экране работало и взаимодейтсвовало 5 инстансов рякта и столкнетесь со всеми теми же проблемами и решениями.

зачем мне инжекторы, если для меня это должен быть черный ящик из одного компонента?

бывают задачи шеринга некоторого кода или состояния между компонентами, можно пытаться ограничится одними эвентами, но это будет несколько экстенсивно
вы писали что его надо дефайнить прямо сразу в том же жс выдав себя за боба;)

Видимо вы не уловили логическую связь между 2мя предложениями. Если бы вы прочитали следующее предложение, то поняли бы, почему Джордж вынужден дефайнить компонент внутри:

Пользовательский код компонента datetime-chooser вообще не должен знать что внутри есть какой-то там date-select, потому что это означает вникать в детали реализации.


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

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

Не знаю, что конкретно вы подразумеваете под статической сборкой, но уже давно есть динамическая подгрузка компонентов и code-splitting. Которые кстати также основаны es6 стандарте модулей. Подмену компонентов в рантайме также можно легко реализовать в любом фреймворке. Всех этих возможностей хватает, чтобы реализовать любой функционал, а вот полезность возможности отложенного дефайна веб-компонентов до конца не ясна. Думается мне это сделано все из-за тех же модулей, но тогда это никакая не суперспособность, используя import() и вебпак мы получаем модули даже в тех браузерах, где нет нативной поддержки.

Все понимают, что любой вася может собрать хеловорлд СПА на рякте, вы сделайте что-бы у вас безконфликтно на экране работало и взаимодейтсвовало 5 инстансов рякта и столкнетесь со всеми теми же проблемами и решениями.

Стесняюсь спросить, а зачем мне 5 инстансов реакта на странице? Мне трафик девать некуда или что?

бывают задачи шеринга некоторого кода или состояния между компонентами, можно пытаться ограничится одними эвентами, но это будет несколько экстенсивно

Да, «ёшкин код». Мы с вами разве общаемся на тему шаринга кода и состояния? Это вообще отдельная большая тема и отдельная боль при использовании веб-компонентов. Причем тут ивенты тоже?

Еще раз — если я взял сложный 3rd-party компонент и хочу его поместить в свое приложение:

  1. Я НЕ должен вникать в его структуру и хоть как-то инжектить/дефайнить его внутренние компоненты и другие детали реализации. Все это нарушение инкапсуляции, да и просто не удобно.
  2. Я НЕ должен получить «протекающие» из этого компонента наружу внутренние компоненты. То есть присловутый date-select вообще не должен хоть как-то появиться во внешнем по отношению к родительскому компоненту коде.
  3. Я должен иметь возможность просто взять и подключить его в свое приложение, без страха получить эксепшен.
  4. Для того, чтобы считать систему регистрации веб-компонентов хоть сколько то рабочим решением, я НЕ должен быть вынужден обмазаться с ног до головы DI/инжекторами/депенденситрекерами/other bullshit, иначе это не готовая к использованию система, а просто костыль.


то поняли бы, почему Джордж вынужден дефайнить компонент внутри


он не должен этого делать ни в каком случая, в этом сила веб-компонентов, что вы можете дефайнить компонеты потом в том числе и для динамического рендеринга

Подмену компонентов в рантайме также можно легко реализовать в любом фреймворке.


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

Еще раз — если я взял сложный 3rd-party компонент и хочу его поместить в свое приложение


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

Да, «YOбушки-воробушки». Хорошо, кто тогда должен задефайнить компонент date-select, чтобы я мог использовать его родительский компонент datetime-chooser? Напишите пожалуйста в коде. Хватит голословных утверждений.

подмена это небезопасная коллизионная история, мне кажется так делать просто недопустимо, т.к. непонятно что делать с уже отрендеренными компонентами, непонятно почему ваши компоненты может кто-то подменить.

Вы из какого века вообще? Это давно уже делается и четко работает. Пример, у меня есть точка монтирования компонентов-страниц, куда в зависимости от текущего роута монтируется нужный компонент. Все это работает на ура, без каких либо проблем, практически во всех современных фреймворках.

Вы можете в частном порядке разрешать конфликты присваивая им другие тегнеймы.

Какие еще тагнеймы? Я про компоненты фреймворков тут писал, а не про WC. То что этого сделать на WC нельзя просто потому что они такие, итак понятно.

вы лично может не хотите, а кому-то без этого не решить задачи.

Может хватит «воды»? Давайте конкретный пример, где без этого не обойтись, иначе это не аргумент.

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

Конкретнее, что и чем ограничивает и как с этим борятся веб-компоненты?

Пока все что вы пишете, это просто набор букаф. Судя по общему треду, я не один сделал такой вывод по отношению к вам.

если фреймворки оборачивают стандартное апи и делают это не очень казуальным образом, то наверное в этом нет проблемы, но большинство популярных фронтенд фреймворков не только не следует стандартам но разрабатывается поперек паттернов (принципов) разработки ПО, создавая этакий мирок или секту живущую по правилам задом-наперед
Мы явным образом импортируем компонент Button. Если удалить импорт, то у нас произойдет ошибка в рендеринге. С веб-компонентами ситуация другая, мы просто рендерим html-тэги, а они магическим образом оживают.


это называется слабая связность, когда она между компонентами или модулями это дает преимущества масштабируемости системы: вы можете добавлять и изымать части системы без нарушения ее работоспособности. В рякте же все с ног на голову: слабая связность применена между логикой представления (его компонентами) и бизнес-логикой (редакс и пр.), что усложняет разработку, у меня например не работало автодополнение в среде разработки, следовательно будут пропускаться и ошибки, а прямая связность — в лейауте, что сильно снижает открытость архитектуры для изменений.
Слабая связность хороша, когда она делается опционально, по желанию. То есть я мог бы при желании параметризовать компонент Icon для кнопки, чтобы желающие могли его подменить.

Но бывает нужна и жесткая связь. Есть кнопка, и она собрана и протестирована с вполне конкретной иконкой и ее замена не гарантирует работоспособность. (например, под иконку зарезервировано 16х16px, а новая иконка будет 20х20px). Обязательная слабая связность заставляет разработчиков раскрывать потребителям свои детали реализации, что ухудшает обратную совместимость компонента.
жетская связь не позволит сделать расширяемую систему, каждый раз когда вы изменяете кнопку, вам придется менять/пересобирать/перезагружать и связанные с ней компоненты. ML языки априори слабосвязные, т.к. их основная задача обеспечивать расширяемую семантику документа, модульные и компонентные системы должны быть слабосвязными для задач масштабирования и адаптации, но когда вы делаете слабую связь между самой кнопкой и сбинденым на нее действием это как раз тот случай когда собирать воедино и отлаживать все будет проблематично.
Мне почему-то кажется что в lit-element не встроенного VDOM. Там под капотом lit-html, который работает иначе.
сколько лет прошло, а до сих пор читаю статьи из серии:
После прочтения этой статьи может показаться, что веб-компоненты плохие и у них нет будущего
стоит отметить, что даже фреймворки использующие веб-компоненты делали это, как-бы это сказать, не очень привлекательно с точки зрения архитектора и инженера, так например многие использовали разные «шаблонизаторы» надстраивающие или подменяющие native templates, когда в них нет особой необходимости, нарушающие принцип разделения ответственностей хтмл импорты, старый страшный синтаксис джаваскрипта и другие причуды, т.е. примеры их практического использования не выглядели выйгрышно в сравнении с популярными фреймворками, которые не используют браузерные стандарты
UFO just landed and posted this here
не лучше, т.к. кучу кода вы можете унифицировать в методе или классе, а явно захаркоживаемые в шаблон аттрибуты создают дополнительную сложность и интеграции и развитии при изменении дизайна-верстки вы переверстываете весь шаблон допуская много ошибок с этими аттрибутами и тратя кучу времени, переписываете код, а когда в шаблоне нет особенных синтаксических конструкций вы только переписываете код, может быть даже в минимальном объеме%)
UFO just landed and posted this here
обычно все эти аттрибуты добавляются к исходной верстке в исходно обычный хтмл (если фреймворк требует полного переписывания это отдельная боль, чаще от работы с дизайном в таких системах просто отказываются), т.е. у вас в процессе получается 2 шаблона, макетный и фреймворковый. Каждый такой атрибут это потенциальный баг, т.к. велика вероятность, что разработчик-интегратор его пропустит, опечатается или что-то такое еще сделает случайно-произвольное. Кроме второго шаблона, вам все равно надо еще докодировать еще настоящей бизнес-логики, или доинтегрировать если это не первая итерация и тут количество потенциальных ошибок будет возрастать геометрически помноженное на проблемы коммуникации если этим занимаются разные узкие специалисты. В тоже время в промежуточном шаблоне нет необходимости, т.к. хтмл вместе с цсс селекторами сам по себе является прекрасным шаблонизатором, т.е. вам достаточно иметь некоторый обычный хтмл + цсс и js код производящий всю связывающую магию ориентируясь на свою конфигурацию и адресуя элементы по селекторам с появлением shadow dom даже снова можно вспомнить про более эффективные с точки зрения производительности айдишники, поиск внутри под-дерева не будет тормозить в любом случае, а прямой биндинг данных даст безусловный выйгрыш относительно разных хитрых придумок с дифом перерисовок или масштабированием операций изменения.
UFO just landed and posted this here
вы можете использовать и onclick=«elementId.someMethod()», однако кроме биндинга эвентов шаблонизаторы и фреймворков привносят еще много своих констркуций (аттрибуты биндинга, анимации, конфигурации данные и т.п.), которыми разработчики активно пользуются (а как же не пользоваться если так проще) создавая систему из 2х шаблонизаторов, потому что сразу на коде фреймворка сделать макет выйдет равноценно полной реализации. Я не вижу большой порочности в походе бекбона, хотя ее можно было бы улучшить прямым биндингом, есть люди которые вообще фантизируют разработку искусственным интеллектом, а не только без работы над дизайном-макетом. Понятно, что можно просто использовать компоненты цсс фреймворка для многих случаев, но вы просто понижаете градус задач говоря «ах, раз этого нет значит оно и не нужно».
UFO just landed and posted this here
Насколько я помню, это не работает для Custom Events.

вообще, я был сторонником addEventListener и прочего биндинга-хендлинга сугубо в коде, на мой взгляд правильнее добавить проверки и бросить иключение или даже ворнинг если элемент не был найден селектором. Что до повторного упоминания айдишника, то при биндинге в шаблоне вы точно так же дважды минимум упоминаете имя метода-обработчика, так что тут как ни крути:) но наверное можно использовать особенность мапинга элементов по айди на глобальный (или может уже и стековый для компонента в теневом поддереве) скоуп
Тут связь обсуждаемого и CSS-фреймворков я не уловил.

что-бы произвести биндинг или рендеринг на шаблон вам не надо дополнительно размечать его специальными аттрибутами, можно использовать селекторы для адресации элементов, как раз как-то так было в бекбоне, но там по умолчанию имя метода-обработчика тоже задавалось строкой. Вы конечно возразите, что мол компайл-тайм нахождение ошибок будет надежнее, однако, компиляция это на самом деле транспиляция, и в какомнить рякте вам всеравно все преимущества прямого связывания нивелируют развязанными пропсами или другой, но той же по сути шиной событий
UFO just landed and posted this here
Ну… это хотя бы позволяет использовать возможности IDE


вот в примере с реактом-редаксом, который я привожу в данном среде, у меня интелиджа не могла зайти в определение прокинутого через пропсы метода, а когда я внутри своего класса-вебкомпонента дергал методы заинжекченного метода сервиса — могла, т.к. его контракт определялся типом свойства класса.

При следовании архитектуре веб-компонентов, все внутренние обработчики будут внутри класса-компонента, все внешние вы и так не узнаете если они «прокинуты через пропсы», хотя, на самом деле, в случае нативного кода все прямые бинды достаточно просто вычисляются из Web Developer Tools а непрямые через свойство path у эвента который вы поймаете дебагером, а вот если у вас модульное приложение на фреймворке со свой шиной и биндингом это не понятно как сделать, а если вы имели ввиду монолит это немного не тот класс решаемых задач.
UFO just landed and posted this here
илнайна верстки в джаваскрипте ничто не может оправдать, извините, т.к это нарушение принципа разделения ответственностей и всего прочего mvc. Понятно, что лично вам может быть говнокодить удобненько. Но я много и много раз видел вермешели смешивающего кода в который невозможно (противно) было развивать и поддерживать. Прикладные задачи всегда превращают такой код в помойки говнокодов.
UFO just landed and posted this here
>> [известная картинка с разными точками зрения на то, что такое компонент]

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

говнокодом чаще используют именно описанный вами подход


это были лихие нулевые, браузерное апи и сам джаваскрипт были убогими, нахлобучки типа жквери страшными и такими же сиюминутно мотивированными «мне просто календарик заанимировать», т.е. вот это вот самое принесение в жертву принципов разработки субъективному удобству решения оперативной задачи и породило тот самый ужас, который вы не хотите видеть модных ныне подходах
UFO just landed and posted this here
чем по непонятным причинам стремиться к абсолютной синтаксической чистоте HTML, CSS и JS в пределах вью.


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

Я хотел понять какая есть альтернатива, вы объяснили, мне не понравилось — ну, бывает.


важно понимать, что альтернатива может существовать, ее конкретных реализаций в современных фреймворках я и правда не видел, но дело тут в том, что 90% современного фронтенда слепо увлечены анти-паттерновыми решениями (в популярных сейчас фреймворках) и бестолковыми идеями навроде таких, что веб-разработка больше не нужна и все заменит искусственный интеллект и конструкторы сайтов с готовыми виджетами или что у них есть какая-то такая важная оптимизационная идея-причина, которая отменяет инженерные практики
UFO just landed and posted this here
Есть ли реальные юз кейсы, где видно пользу от предлагаемого вами решения? Пока мне видны только минусы.


паттерны были разработаны на слезах и крови разрабатывающих как им кажется быстрее и прямо сейчас удобнее поэтому практические примеры подтверждающие правильность их использования разработчику должны по идее встречаться регулярно, ну может быть лично вам повезло работать только со своими нерасширяемыми велосипедами конечно и только писанными лучше вашего собственного уровня и только на задачах в русле возможностей и ограничений предпочитаемой технологии или системы, но мой опыт говорит об том, что технологии разработанные по сиюминутным представлениям не переживают активной фазы своих создателей, т.е. 1-3 лет развития, тот же жквери в свое время имел множество сторонников и претензий к нему на том уровне понимания задач было мало, а теперь никому кроме пенсов он не кажется хорошим решением
UFO just landed and posted this here
1) На счет производительности стилей, в скорости инцилизации мы явно имеем проигрыш, а вот что насчет обновления? А я скажу что, в пару раз быстрее, так что shadowDOM позволяет нам очень быстро модифицировать стили в отличие от lite dom.
2) На счет Tree-shaking и жесткой связанности с импортами: очень просто решается путем написания небольшой ф-и(лучше декоратора в случае ТС) которая одновременно регистрирует компонент в риесторе элементов и перегружает toString у класса, чтобы toString возращал тэг.В итоге мы получаем что-то вроде
import { Button } from './button'


render () {
return `<${Button}></${Button}>`
}

3) При обновлении нескольких пропертей в том же LitElement как и во всех адекватных фраемворках изменения бачуются и вызывется один перерендр
А я скажу что, в пару раз быстрее, так что shadowDOM позволяет нам очень быстро модифицировать стили в отличие от lite dom.

Интересное предположение. А бенчмарк покажете?


На счет Tree-shaking и жесткой связанности с импортами: очень просто решается

Тут две проблемы


  1. Lit-html динамические значение в именах тегов не поддерживает: https://github.com/Polymer/lit-html/issues/78
  2. Даже если вы экспортируете компонент как константу, его все равно можно инстанцировать напрямую, без импорта. И по закону Мерфи это конечно же произойдет.

При обновлении нескольких пропертей в том же LitElement как и во всех адекватных фраемворках

Это хорошо, что во фреймворках есть решение. Но изначально евангелисты гугла и компания вещали нам, что в веб-компонентах все уже есть, что фреймворки поверх получатся маленькие и легкие. А в реальности оказалось, что нужно и с батчингом заморачиваться, и с умным обновлением DOM (см. lit-html) и так далее по тексту статьи.

Хм, сколько комментариев и никто не озвучил самый большой недостаток веб-компонентов — невозможность разбить на компоненты svg-элементы. Вот допустим вы хотите написать какое-то сложное приложение где будут графики, кривые безье и и.д. И если все эти отдельные отдельные svg-элементы можно динамически создавать, менять аттрибуты, добавлять обработчики и т.д (то есть все как с обычными html-элементами) то вот декомпозировать и разбить на отдельные веб-компоненты у вас не получится потому что кастомные элементы не поддерживают svg. В то время как используя любой из популярных фреймворков (реакт, ангуляр, vue и т.д) я могу разбить svg-верстку на отдельные компоненты добавив им поведение и инкапсулировать логику (то для чего были придуманы компоненты) то с веб-компонентами я это сделать не могу. Facepalm.
Хорошый поинт, я до svg просто не дошел в своих попытках работы с веб-компонентами. Спасибо за информацию!

Articles