Веб-компоненты в реальном мире


    Photo by NeONBRAND


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


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


    Что такое веб-компоненты


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


    • Custom elements – возможность регистрировать свои html-тэги с определенным поведением
    • Shadow DOM – создание изолированного контекста CSS
    • Slots – возможность комбинировать внешний html-контент со внутренним html компонента

    В качестве примера напишем hello-world компонент, который будет приветствовать пользователя по имени:


    // веб-компоненты должны наследоваться от стандартных html-элементов
    class HelloWorld extends HTMLElement {
      constructor() {
        super();
        // создадим Shadow DOM
        this.attachShadow({ mode: "open" });
      }
    
      connectedCallback() {
        const name = this.getAttribute("name");
        // Отрендерим наш контент внутрь Shadow DOM
        this.shadowRoot.innerHTML = `Hello, <strong>${name}</strong> :)`;
      }
    }
    
    // зарегистрируем наш компонент как html-тэг
    window.customElements.define("hello-world", HelloWorld);

    Таким образом, каждый раз, когда на странице будет размещен тэг <hello-world name="%username%"></hello-world>, на его месте отобразится приветствие. Очень удобно!


    Посмотреть этот код в действии можно здесь.


    Вам все равно понадобятся фреймворки


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


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


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


    Еще часто говорят о пользе веб-компонентов в виде уменьшения размера загружаемого Javascript. Однако lit-element, который использует веб-компоненты весит в лучшем случае 6 кб, в то время как есть preact, который использует свои компоненты, похожие на React, но при этом весит в 2 раза меньше, 3 кб. Таким образом, размер кода и использование веб-компонентов вещи ортогональные и одно другому никак не противоречит.


    Shadow DOM и производительность


    Для стилизации больших html-страниц может понадобится много CSS, и придумывать уникальные имена классам может оказаться сложно. Здесь на помощь приходит Shadow DOM. Эта технология позволяет создавать области изолированного CSS. Таким образом, можно отрендерить компонент со своими стилями, которые не будут пересекаться с другими стилями на странице. Даже если у вас будет имя класса, совпадающее с чем-то еще, стили не смешаются, если каждый из них будет жить в своем Shadow DOM. Создается Shadow DOM вызовом метода this.attachShadow(), а затем мы должны добавить внутрь Shadow DOM наши стили, либо тэгом <style></style> либо через <link rel="stylesheet">.


    Таким образом, каждый экземпляр компонента получает свою копию CSS, что очевидно должно сказаться на производительности. Вот это демо показывает, насколько именно. Если рендер обычных элементов без Shadow DOM занимает порядка 30мс, то с Shadow DOM это около 50мс. Возможно, в будущем производители браузеров улучшат производительность, но в настоящее время лучше отказаться от мелких веб-компонентов и постараться делать компоненты типа <my-list items="myItems"> вместо отдельных <my-item item="item">.


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


    Глобальные имена компонентов


    Каждый веб-компонент привязывается к своему имени тега с помощью customElements.define. Проблема в том, что имена компонентов объявляются глобально, то есть если кто-то уже занял имя my-button, вы ничего не сможете с этим сделать. В маленьких проектах, где все имена компонентов контролируются вами, это не представляет особой проблемы, но если вы используете стороннюю библиотеку, то все может внезапно сломаться, когда вы они добавят новый компонент с тем же именем, что вы уже использовали сами. Конечно, от этого можно защититься конвенцией именования с использованием префиксов, но такой подход сильно похож на проблемы с именами CSS-классов, избавление от которых нам обещали веб-компоненты.


    Tree-shaking


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


    import { Button } from "./button";
    
    //...
    
    render() {
      return <Button>Click me!</Button>
    }

    Мы явным образом импортируем компонент Button. Если удалить импорт, то у нас произойдет ошибка в рендеринге. С веб-компонентами ситуация другая, мы просто рендерим html-тэги, а они магическим образом оживают. Аналогичный пример с кнопкой на lit-element будет выглядеть вот так:


    import '@polymer/paper-button/paper-button.js';
    
    // ...
    
    render() {
      return html`<paper-button>Click me!</paper-button>`;
    }

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


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


    import { Button, Icon } from './components';
    
    //...
    
    render() {
      return <Button>Click me!</Button>
    }

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


    Проблемы с типизацией


    Javascript по своей природе динамический язык, и это нравится не всем. В больших проектах разработчики предпочитают типизацию, добавляя ее с помощью Typescript или Flow. Эти технологии прекрасно интегрируются с современными фреймворками типа React, проверяя корректность вызова компонентов:


    class Button extends Component<{ text: string }> {}
    
    <Button />  // ошибка: отсутствует обязательное поле text
    <Button text="Click me" action="test" />  // ошибка: лишнее поле action
    
    <Button text="Click me" /> // все как надо, ошибок нет

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


    namespace JSX {
      interface IntrinsicElements {
        'paper-button': {
          raised: boolean;
          disabled: boolean;
          children: string
        }
      }
    }

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


    const component = document.querySelector('paper-button') as PaperButton;

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


    Групповое обновление свойств


    Нативные браузерные компоненты, такие как <input> или <button>, принимают значения в виде текстовых атрибутов. Однако, иногда может понадобиться передавать более сложные данные в наши компоненты, объекты, например. Для этого предлагается использовать свойства с геттерами и сеттерами.


    // находим наш компонент в DOM
    const component = document.querySelector("users-list");
    
    // передаем в него данные
    component.items = myData;

    На стороне компонента мы определяем сеттер, который эти данные обработает:


    class UsersList extends HTMLElement {
      set items(items) {
        // сохраняем значение
        this.__items = items;
        // перерисовываем компонент
        this.__render();
      }
    }

    В lit-element для этого есть удобный декоратор – property:


    class UsersList extends HTMLElement {
      @property()
      users: User[];
    }

    Однако, может случиться ситуация, что нам нужно обновить несколько свойств сразу:


    const component = document.querySelector("users-list");
    
    component.expanded = true;
    component.items = myData;
    component.selectedIndex = 3;

    Каждый сеттер вызывает рендеринг, ведь он не знает, что там будут обновлены и другие свойства. В результате у нас будут два лишних обновления, с которыми нужно что-то делать. Стандарт ничего готового не предоставляет, поэтому разработчикам нужно выкручиваться самим. В lit-element это решают асинхронным рендерингом, то есть сеттер не вызывает обновление напрямую, а оставляет запрос на отложенный рендеринг, что-то вроде setTimeout(() => this.__render(), 0). Такой подход позволяет избавиться от лишних перерисовок, но усложняет работу с компонентом, например его тестирование:


    component.items = [{ id: 1, name: "test" }];
    // не сработает, рендер еще не произошел
    // expect(component.querySelectorAll(".item")).toHaveLength(1);
    
    await delay(); // нужно подождать пока обновление применится
    expect(component.querySelectorAll(".item")).toHaveLength(1);

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


    Выводы


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


    • Встраивание клиентской логики в большой сервер-рендерный проект. По такому пути сейчас идет Github. Они активно используют веб-компоненты для своего интерфейса и даже опубликовали в open-source некоторые из них. В ситуации, когда у вас большая часть страницы статическая или рендерится сервером, веб-компоненты помогут придать интерактивности некоторым частям.
    • Реализация микро-фронтендов. На странице рендерятся независимые виджеты, которые могут быть написаны на совсем разных фреймворках и разными командами, но им надо как-то уживаться вместе. При этом они вываливают свой CSS в глобальную область и всячески мешают друг другу. Для борьбы с этим у нас раньше были только iframe, теперь же мы можем завернуть отдельные микро-фронтенды в Shadow DOM, чтобы они жили там своей жизнью.

    Есть также и вещи, которые я бы на веб-компонентах делать не стал:


    • UI-библиотека получится неудобной, по причине проблем с tree-shaking и типами, которые раскрыты в этой статье. Написание UI-компонентов (кнопок, инпутов и т.д.) на том же фреймворке, что и основная часть страницы (React, Vue и пр.) позволит им лучше взаимодествовать с основной частью страницы.
    • Для основонго контента страницы веб-компоненты не подойдут. С точки зрения пользователя, рендеринг страницы с единственным веб-компонентом <my-app /> ничем не отличается от использования SPA-фреймворка. Пользователь будет вынужден ждать пока прогрузится весь Javascript, чтобы наконец-то увидеть контент. И если в случае Angular/React/Vue это можно ускорить путем пре-рендера страницы на сервере, то в случае веб-компонентов таких возможностей нет.
    • Инкапсулировать части своего кода в веб-компоненты тоже смысла нет. Вы получите проблемы с производительностью, отсутствие типов и никаких особых преимуществ взамен.

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

    Поделиться публикацией

    Комментарии 334

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

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


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

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

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

          +5

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


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

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

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

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

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

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

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

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


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


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

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

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

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


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

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

              0

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


              import { Button as ButtonA } from 'lib-a'
              import { Button as ButtonB } from 'lib-b'
              
              customElements.define('button-a', ButtonA)
              customElements.define('button-b', ButtonB)

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

                +6

                Возникают проблемы с транзитивными зависимостями. Уже ответил выше.

                  0

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


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


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

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


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


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


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

                    0

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


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

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

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

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

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

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

            На самом деле тема очень полезная, у нас большая компания, пишем на разных шаблонизаторах и веб компоненты помогают реюзать компоненты между ними. Но без какой то прослойки типа lit-element крупные вещи действительно лучше не писать.
              +1
              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 только после обновления всех свойств. А как вы будете оптимизировать свой собственный компонент?


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

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

                0
                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, у меня своя микро-надстройка. Просто на сеттере свойства я меняю только то что мне нужно, поэтому поведение полностью наследуется от нативного =)

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

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


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

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


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

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

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

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

                      Даже если взять самый умный шаблонизатор, проблема с 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. Проблема в том, что нет стандартного решения, каждый автор компонента будет делать по-своему.

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

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

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

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

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

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


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

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

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


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

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

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

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

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

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

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


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

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


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

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


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

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


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

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

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

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

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

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

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


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

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


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

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

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

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

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

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

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

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

                                            SvelteJS — 0Кб ;)

                                              +2

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


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


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


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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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


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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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


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

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


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

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


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

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


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

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

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

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

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

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

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

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

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

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

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


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

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

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

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


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

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

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

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

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

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

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


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

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


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

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

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

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

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


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

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

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


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

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


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

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

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

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


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

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

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

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

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

                        Не расскажете в двух словах, как оно там работает? Тут пишут, что lit-html VDOM не использует, а как оно в lit-element я не знаю.
                          –1
                          lit-element использует самый обычный lit-html, здесь скорее вопрос терминологии.

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

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

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

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

                                  0
                                  Спасибо за информацию! Но, кажется, недостающая фича ещё больше уменьшает смысл lit-html и его подхода
                                    0
                                    У 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
                                  0
                                  И все же vdom — это vdom. Это далеко не общий термин и он ни разу не обобщает подходы к повышению эффективности манипуляций в DOM. В том же Angular vdom нет, в Svelte тоже его нет, также как в lit-html, при это все они пытаются делать изменнения в DOM максимально эффективно. Полагаю без таких вещей как render virtual tree & reconcile, считать что-то vdom значит намеренно сужать разнообразие подходов. Именно в vdom полно маркетинга, поэтому многие молодые разработчики думают что на vdom свет клином сошелся.
                            +1
                            Большая часть тезисов и выводов данной статьи весьма спорна, это мягко говоря. С веб-компонентами нет никаких особых проблем ни с контролем зависимостей (реестр компонентов дает вам всю необходимую информацию о том, что вы регистрируете в рантайме в любое время), ни с типами (вы вполне можете писать свой код на TS и создавать тайпинги для своих тегов) ни, тем более, с производительностью (автор бы сравнил скорость рендера с react/vue-компонентами, справедливости ради, а еще сам код можно разобрать по косточкам, ибо в нем речи не идет о компонентах, сравнивается теплое с мягким). Сфера применения указана также весьма странно, видно что автор копнул тему но явно недостаточно глубоко. Про VDOM тоже ерунда написана, в подходе с веб-компонентами вам вообще не обязательно иметь какие-либо промежуточные сущности между DOM и данными, вы можете производить инъекции максимально эффективно через старый добрый DOM API. Очень не советую рассматривать данную статью как какое-либо руководство к действию. Но с тем, что веб-компоненты это не замена фреймворкам, конечно, стоит согласиться, их скорее стоит рассматривать как основу для фреймворков нового типа, а также как композиционную основу для построения собственных велосипедов. В этой роли — они великолепны.
                              0
                              автор бы сравнил скорость рендера с react/vue-компонентами, справедливости ради

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



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


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

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


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

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


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

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

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


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

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

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


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

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

                                        0
                                        если сильно отличается это должны быть разные шаблоны, каждый из этих шаблонов вы уже имеете в объектной модели браузера, быстро и дешево клонируете и подрендериваете динамические данные, тут надо понимать, что вам не обязательно перерендеривать что-то или даже все, на каждое изменение, т.к. вы можете сбиндить логику делающую простую перезапись данных по ссылке при проявлении изменений в системе.
                                  0
                                  Во первых, ситуацию с 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
                                    0
                                    > Также, именно по этой причине, любой фреймворк, основанный на близком подходе будет медленнее примерно раза в 2 (и больше) чем при использовании нативного парсинга шаблона до вставки элемента на страницу.

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

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

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

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

                                                github.com/zakangelle/generator-redux-stack

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

                                                  1. localvoid.github.io/ivi-examples/benchmarks/dbmon/?m=1
                                                    –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
                                                            })();
                                                    
                                                      +1
                                                      Что это за странный юзкэйс? Зачем вы трогаете innerHTML у одного элемента 1 миллион раз за фрэйм. Все современные декларативные библиотеки умеют батчинг.
                                                        0
                                                        А еще батчинг умеет сам браузер, и делает это оптимальнее js.
                                                          0
                                                          А ещё нужно показывать цифры прежде чем продолжать делать различные заявления.
                                                          0
                                                          я трогаю не элемент а прокси объект, вообще я сделал такой же точно по входным тербованиям пример на реакте (вызывал инкремент у редакса) и он выжирал всю память и заваливал вкладку не обновив значение ни разу, потом я его упростил убрав функцию бенчмарка, но ничего не поменялось, для меня этот код выглядел вполне естественным. У меня сложилось гипотеза, что в случае с нативом браузер оптимизировал цикл высчитав финальное значение и отрисовав сразу, но продолжая колбасисть код бенчмарковых фукнций 1000и раз и в случае с реактом он этого сделать не смог, а может быть пытался построить какую-то оптимальную цепочку рекурсивного вызова своего инкрементального рендера
                                                            0
                                                            > вообще я сделал такой же точно по входным тербованям пример на реякте (вызывал инкремент у редакса)

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

                                                                Традиционный клиент-сервер юзкэйс когда сервер отправляет снэпшоты данных невозможно решить без дифф алгоритма, тк отсутствуют какие-либо данные о том как нужно переставлять дом элементы чтобы прийти к конечному состоянию. Если будете обновлять с помощью innerHTML, то потеряете внутреннее состояние всех компонентов.
                                                                  0
                                                                  когда есть геттеры/сеттеры и прокси, зачем вам дифф алгоритм? изменять данные и связи всегда дороже чем создавать новую копию на основе старых и этого изменения, а у компонентов и не должно быть состояния, которое нельзя потерять вместе с компонентом
                                                                    0
                                                                    Спортируйте эти ~60 строчек кода[1] написаные с использованием lit-html на ваниллу и все вопросы отпадут.

                                                                    1. github.com/localvoid/uibench-lit-html/blob/0fab2ca944c5dc585bc5c595ff43d7a0f0fc289a/src/main.js
                                                                      0
                                                                      да этот пример просто расширить скорее всего не выйдет, а вот на хорошо структурированный код angular-material/cdk я легко менял под свои задачи наследуя, расширяя и переопределяя классы компонентов, шаблоны, не переписывая весь грид с нуля, не копипастя и даже не особенно вникая во внутреннее устройство. В этом главная задача технологий — быть расширяемыми и доступными для участия в доработке и развитии другими людьми желательно не сильно завися от моды.
                                                                        0
                                                                        Причём тут расширить? Это простой пример когда приходит снэпшот данных и нужно обновить DOM структуру, не теряя внутреннее состояние. ~60 строчек кода на любой современной библиотеке, вот к примеру тоже самое на React[1]. Реализуйте тоже самое поведение без использования библиотек вроде lit-html, это ведь так легко «когда есть геттеры/сеттеры и прокси».

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

                                                                            пусть будет внутреннее состояние элементов: css анимации, позиция скролла, позиция курсора в инпут полях, документ в ифрэйме, медиа элементы и куча других кэйсов.
                                                                              –1
                                                                              эти параметры уже существуют в базовых элементах и лучше как раз через сеттеры геттеры их смапить прямо или менять через евенты, а не хранить. Так или иначе веб-компоненты вас в этом никак не ограничивают, как вам кажется необходимым так и можно сделать, единственно, что какие-то арихитектуры навроде реактовской я бы бездумно воспроизводить не стал, т.к. они придумывались как ответ на кашу-вермишель фронтенд технологий 10и летней давности, а с вебкомпонентами все поменялось и браузер может сам решать задачи сборки мусора или оптимизации
                                                                        0
                                                                        т.е. даже если бы этот код не тек, а делал все быстрее всех, толку от него как от выгравированной в камне веб-страницы
                                                      –1
                                                      habr.com/en/post/443032/#comment_19864502 — вот для начала можно сравнить с тем, что привел автор статьи.
                                              0
                                              Во вторых: сделайте, наконец, корректный тест. Отобразите на странице 1000 компонентов, обязательно с одинаковой структурой, созданных с помощью LitElement, React и на чистых компонентах.

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


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

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

                                                и завернуть это в компоненты по стандарту?
                                                  0
                                                  Еще упустил, в случае с preact у вас все элементы рендерятся просто внутри шаблона ОДНОГО компонента по сути… Это честно по вашему?
                                                    0
                                                    Я пишу код так, как я бы его писал в реальном проекте. Если есть похожий паттерн на веб-компонентах, давайте его тоже использовать.
                                                  0
                                                  Вот пример на скорую руку:
                                                  <!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
                                                    Запустил ваше демо, получил рендеринг за 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>
                                                    


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



                                                        Svelte тут староват конечно. В 3-й версии были сделаны многие улучшения, но в целом сути это не меняет.
                                                      +1
                                                      Для интереса взял ваш код и код 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 кода.

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

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

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

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

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

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

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

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


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

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


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


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

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

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

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

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

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

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

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

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

                                                                    0
                                                                    хорошо, он неправильно тестирует веб компоненты:)
                                                                      0
                                                                      Ему об это и напишите, мне то зачем? Я и не могу понял, где вы в Svelte нашли работу со строками. Ее там не то что в рантайме, даже при компиляции нет.
                                                                    +1
                                                                    Расскажите, как нам нативно склонировать native template в наш компонент? Окей, для синтетического примера вы поместите один template тег в тело документа и заберете его querySelector-ом. А в условиях веб-приложения? Все темплейты будете в одном HTML хранить? Или вы знаете секретный способ импортировать documentFragment в js из отдельного файла нативно? Или вы предлагаете использовать HTML Imports, которые obsolete и не уже рекомендуются к использованию разработчиками браузеров? Или все ж придется экспортировать js-строку и парсить ее потом?
                                                                      –1
                                                                      для не SPA это не проблема, что-бы все необходимые темплейты находились в одном хтмл, кроме того в фронтенд-фреймворках довольно модная тема — server side compilation, где по роутам создаются предкомпилированные бандлы, так что тут как с роутингом и инжекцией зависимостей все на совести разработчиков фреймворков
                                                                        +1
                                                                        Даже и не знаю, как это прокомментировать :)
                                                                        Мы уже внезапно и не про SPA оказывается общаемся, и сразу из фреймворков(тех, что корпорациями проплачены и неверным путем идут?) оказывается находятся какие-то альтернативные решения. А как же стандартные API, они же такие крутые?

                                                                        Если честно, мне все ваши комментарии в этом посте напоминают фразу «слышал звон, да не знает где он». На вопросах, которые не укладываются в ваши тезисы вы сразу сливаетесь.
                                                                          –1
                                                                          Мы уже внезапно и не про SPA оказывается общаемся

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

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


                                                                            Это считается? Все отдельно, как вы советуете.
                                                                              0
                                                                              да, так правильнее конечно
                                                                                0
                                                                                Раз выходной файл у Svelte — JS, то считается, так оно работает насколько я знаю везде, просто с разным синтаксисом.

                                                                                Суть всегда одна — мы импортируем HTML в JS-компонент, JS не поддерживает пока импорт HTML(а значит «нативных шаблонов»), а значит мы импортируем строку и парсим ее в DOM.

                                                                                Альтернатива была — импортировать JS в HTML-компонент — это как раз HTML Imports, и да, там отсутствуют затраты на парсинг. Но нет больше HTML Import-ов.
                                                                                  –1
                                                                                  тут кто-то ругал custom elements за глобальное пространство имен, вот разве html imports не тот же настоящий глобал? как быть с потенциальными уязвимостями? вдруг кто-нить трояна в килотонны вермишели засунет? у схожего по смыслу iframe сейчас сделали очень много ограничений по безопасности в силу этой проблемы
                                                                                    +1
                                                                                    И? Продолжим дискуссию после того, как покажете, как использовать native templates тру-вэй, не пихая при этом все шаблоны в один файл.
                                                                                      –1
                                                                                      я пихаю все шаблоны в разные файлы, т.к. разрабатывал с сервер-сайдными технологиями%)
                                                                                        +1
                                                                                        Подытожим:
                                                                                        — тест на производительность неправильный, потому что парсит js-строки, а не использует нативный парсинг HTML
                                                                                        — правильный тест на производительность при этом написать нельзя, потому что придется либо использовать deprecated стандарт, либо согласиться с тем, что решение из теста не масштабируемое
                                                                                        — при этом все равно то, что у других в тестах — неправильно, потому что они не используют нативную шаблонизацию(которую использовать невозможно, см. прошлый пункт)
                                                                                        — правильный тест писать не буду, чтобы не позориться
                                                                                        — сам вообще SPA не делаю, короче сливаюсь я, меня раскусили
                                                                                          –1
                                                                                          эм, что вам мешает сделать пример с тегом template и importNode/clone? почему я должен бежать что-то делать для вашей прихоти, особенно если вы сам сделали неправильно
                                                                                            +1
                                                                                            Не надо никуда бежать и ничего делать для меня. Просто не удивляйтесь тогда, что к вам относятся как к п****болу:-).

                                                                                            И причем тут прокси. Вот есть веб-компонент. Вот у него есть темплейт, лежит отдельно рядом с ним в папочке. Покажите как вы импортируете темплейт в компонент «нативно». Используйте хоть importNode, хоть черта лысого.
                                                                                              0
                                                                                              Вот он видимо пример расширяемого-переносимого-нативного компонента ))))

                                                                                              gitlab.techminded.net/finistmart/com.finistmart.showcase.portlet/blob/master/src/main/webapp/js/showcase-list.js
                                                                                                0
                                                                                                это пример использования двух шаблонов, а код прикладной, а не продуктовый, примеры переносимых есть в бибиотеках-компонентах на webcomponents.org и прочих
                                                                                                  0
                                                                                                  Вот такое говно и приходится разгребать.
                                                                                                    –1
                                                                                                    разгребать это когда проект на нмп даже не собирается в девелопмент режиме, так что я уже сочувствую тому кто за вами будет разгребать
                                                                                                      0
                                                                                                      Не знаю, у кого проект на нпм не собирается в девелопмент режиме, если у вас — то откройте для себя package-lock.json
                                                                                                        –1
                                                                                                        да не только, фронтенд откровения это всегда мрак, хорошо еще, что у многих официантов просто скилла и буджета не хватает, что-то отличное от шаблона выдумать, но поскольку популярные фреймворки сами по себе страшны в нарушениях инженерных практик от этого не так что-бы легче
                                                                                                          0
                                                                                                          Короче, все все поняли. Вы просто не шарите и отстали от жизни. Давайте только не будем наращивать вашу экспертизу за счет комментариев на Хабре. Пойдите чтобы курсы какие-то онлайн пройдите что ли. Тогда глядишь и npm освоите.
                                                                                                            –1
                                                                                                            ах-ах)
                                                                                                              0
                                                                                                              Если что, я имел ввиду чисто фронтенд. Предполагаю, что у вас есть опыт в серверной части. С некоторой вероятностью это что-то вроде Javа или .NET. Думаю отсюда, более-менее позитивное отношение к Angular и негативное отношение к остальным фреймворкам. Ну и конечно же все эти загоны про ООП и паттерны.
                                                                                                                0
                                                                                                                я работал со большинством популярных фронтенд (и бекенд, да) технологий за последние лет 10, мое негативное отношение к остальным фреймворком объясняется только их низким качеством и стремлением игнорировать стандарты и паттерны и колхозить ерунду вместо этого. Для старых фреймворков это объяснимо, т.к. джаваскрипт был сам по себе убог и казуален, но теперь такими стали и сами фронтенд разработчики и весь их даже современный код. Кроме того, фронтенд восновном контролируется группировкой комплиментарных микрософту корпораций и вообще разработчиков, а они паталогические говноделы.
                                                                                                  –1
                                                                                                  вы по ссылке не способны пройти)? там все есть кроме прокси, а прокси он может быть использован для обратного биндинга, т.е. от меняющихся данных в интерфейс, он тут при том, что для ориентира
                                                                                                  0
                                                                                                  Справедливости ради, сделал пример как вы просили. Вот код:

                                                                                                  <!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
                                                                                                    может справедливости ради еще финальный отсчет перенести сразу за окончанием цикла, а не когда вам браузер выделит квант рендер-цикла?
                                                                                                    у меня если по-вашему показывало 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');
                                                                                                        });
                                                                                                      0
                                                                                                      может справедливости ради еще финальный отсчет перенести сразу за окончанием цикла, а не когда вам браузер выделит квант рендер-цикла?

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

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

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

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

                                                                                                              # 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 примера на более слабой? Думаю это будет справедливо, а главное возможно уровняет их показатели.
                                                                                                                0
                                                                                                                И чтобы уж для совсем полной картины, сделал пример на 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


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

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

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

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

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

                                                                                                                        В наше время быть быстрее реакта — не очень много чести на самом деле. Полагаю, реакт тормознее и Vue и даже Angular. Поэтому мы сравниваем с более релевантными вещами.
                                                                                                                          0
                                                                                                                          да нет все стандартное, для просто реакта там обновляется 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
                                                                                                                            0
                                                                                                                            По ссылке не увидел вашего бенчмарка, только тот, который я публиковал выше. Не знаю, вы реально тугодум или тролите просто, но я вам писал ровно про вот такие вещи:

                                                                                                                            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 вообще ни разу не про скорость.

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

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

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



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

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

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

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


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

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

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

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

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

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


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

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


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

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

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

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

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

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

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

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

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

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

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

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


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

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


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

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

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

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

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

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

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

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

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

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


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

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

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

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


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

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

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

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

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

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

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

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


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

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


                                                                                              если у вас в одном компоненте все попиленно на подкомпоненты и вы еще например что-то в них там прокид