Пару лет назад я впервые услышал про веб-компоненты (Web Components). Сперва меня это действительно заинтересовало, но как только шумиха вокруг них приутихла, они тут же вылетели у меня из головы. Но, как оказалось, в последнее время прошло интересное движение и поддержка этой технологии значительно выросла. Отзывчивые веб-компоненты, в частности, призваны упростить наш подход к адаптивному дизайну. Как многообещающе звучит!
Вот четыре пункта, с которыми стоит ознакомиться любому разработчику перед началом использования данной технологии:
  • Поддержка технологии;
  • Кроссбраузерная работа;
  • Возможность адаптации в среде удельного проекта;
  • Модульный подход.

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

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


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


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

Почему я хочу их использовать?


Хорошим примером того, когда вы можете захотеть использовать веб-компоненты является задача, где вам требуется создать пользовательский интерфейс, которого нативно не существует в браузере — такие элементы, как селектор цвета, карусель, аккордеон, поле с автодополнением. Можно использовать в качестве альтернативы одним и тем же компонентам, которыми вы пользуетесь из проекта в проект, предварительно лениво кастомизируя их под требования текущего. Это такие вещи, как социальные кнопки, формы подписки или уведомления. С помощью веб-компонентов вы можете связать разметку, стили и скрипты в один герметизированный модуль и использовать HTML-тег (как <color-picker></color-picker>), чтобы ссылаться на него. Это довольно таки знакомо, если вы уже использовали Angular-директивы или компоненты React, но преимущество здесь в том, что данный подход является родным для браузера и «агностиком» фреймворков.

Веб-компоненты дают вам возможность единожды создать UI-элемент и потом использовать его где угодно. Это идеально подходит для таких проектов как живой стилистический справочник (или styleguide), где вы хотите создать библиотеку с единственным источником истины для каждого из компонентов (где каждый компонент попадает только под своё уникальное правило поведения и отображения). Такой подход подразумевает более короткий, минималистичный код, а также наличие готовых UI-компонентов, ссылки на которые вы или ваша команда можете лёгко добавить в текущий интерфейс.

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

<link rel="import" href="http://url.com/subscribe-form.html">


А затем использовать кастомный тег элемента, что определён для данного веб-компонента. Так пользователь может добавить на свой веб-сайт столько кастомных веб-компонентов, сколько он захочет. К примеру, для формы подписки вы можете использовать тег — <subscribe-form></subscribe-form>, таким образом размещая её в одном, или нескольких местах на странице. Конечно, перед тем как сделать это, вы должны убедиться в том, что созданный вами веб-компонент достаточно гибок и будет адекватно работать в ряду различных устройств и размеров экранов.

Переходим от теории к практике


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

К примеру возьмём форму, которую я создал ранее:



Внутри данного шаблона я создал некую базовую разметку для формы:

<ul class="form"> 
  <li class="form__item">
    <label for="name">Name:</label>
    <input id="name" name="name" type="text">
  </li>
  <li class="form__item">
    <label for="name">Email:</label>
    <input id="name" name="name" type="text">
  </li>
</ul>


Моя разметка и стили спрятаны внутри веб-компонента с помощью возможностей, которые предоставляет Shadow DOM спецификация. Данный способ организовывает некую инкапсуляцию, которая даёт мне возможность использовать label и input селекторы свободно, не боясь влияния на них стилей родительского веб-сайта.

Для ясности и краткости, я не буду описывать написание стилей, кроме тех, которые я использовал для отображения разметки. Я использовал комбинацию свойств float: left и display: table для реализации данного интерфейса и избегания поломки при любой ширине.

.form__item {
  display: table;
  float: left;
  width: 50%;  
}

label {
  display: table-cell;
  width: auto;
}

input {
  display: table-cell;
  width: 100%;
}


По ходу урока я буду использовать скриншоты для демонстрации проделанной нами работы:



Теперь у нас все готово, давайте рассмотрим некоторые техники достижения адаптивности.

Медиа запросы


Классический подход, который мы все знаем и любим, так же хорошо работает и в отзывчивых веб-компонентах. Вы можете использовать медиа запросы внутри вашего шаблона в случае, если вы хотите создать какие-либо дефолтные контрольные точки. С другой стороны вы можете использовать «крючки» (к примеру, создавая классы) и применяя их к родительскому контейнеру, таким образом оставляя возможность пользователю самостоятельно принимать решение. В нашем случае, всё, что нам нужно, — это создать контрольную точку, достигая которую мы отменяем свойство float для дочерних элементов и задаём им ширину в 100%.

@media (max-width: 30em) {
  .form__item {
    float: none;
    width: 100%;
  }
}



Однако, одних медиа запросов тут будет не достаточно.

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



Это происходит потому, что веб-компонент не видит своих границ — не имеет представления о контексте.

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

Flexbox-хак


Если вы задумали использовать веб-компоненты в своём проекте и готовы пожертвовать поддержкой старых браузеров (таких как IE9 и тд.), то чуточку Flexbox-магии вам совсем не навредит. Это отличное решение, которое, к тому же, совершенно не требует использование JavaScript.

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

.form {
  display: flex;
  flex-wrap: wrap;
}

.form__item {
  align-items: center;   
  display: flex;
  flex: 1 0 320px;
  flex-wrap: wrap;
  max-width: 100%;
}       

label {
  flex: 1 0 90px;
}

input {
  flex: 1 0 230px;
  width: 100%;
}


Устанавливая родительскому контейнеру display: flex и flex-wrap: wrap, дочерние .form__item выстроются один к одном, блок-о-блок, но нам всё ещё нужно определить несколько правил, чтоб в случае, если контейнер становится слишком мал, дочерние элементы спрыгивали один под другой.

Внутри .form__item мы использовали краткое записание свойства — flex: 1 0 320px, которое можно разложить как: flex-grow: 1, flex-shrink: 0, flex-basis: 320px. Установив flex-wrap: wrap, мы определили, что ширина нашего элемента не станет меньше указанной в 320px, в то время как указав свойство flex, мы разрешили нашему элементу расти и занимать оставшееся свободное место в строке.

Такой же подход я использовал для элементов input и label. Их суммарное значение flex будет равно 320px, что подразумевает, что они будут адекватно отображены и при меньших размерах контейнера.

Давайте посмотрим, к чему привели сделанные нами изменения:



Гораздо лучше! Тем не менее, это не единственный способ решения данной проблемы, их бесчисленное множество.

Запросы соответствующие веб-элементам


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

.form__item[max-width~="30em"] {
  /* Styles here */
}


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

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

В моём примере я использовал CSS Element Queries, созданный человеком по имени Marc J Schmidt. Этот плагин является действительно хорошей реализацией решения данной задачи. Есть также следующие похожие проекты:

По сути, данные плагины используют JavaScript для определения ширины веб-элемента и добавляют ему соответствующий атрибут, тем самым позволяя определять новые соответствующие стили элементу посредством CSS.

.form__item[max-width~="30em"] {
  float: none;
  width: 100%;
}


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

Атрибуты


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

<subscribe-form layout="small"></subscribe-form>


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

В Shadow DOM спецификации контейнер, содержащий в себе элемент, определён как :host. Пример будет выглядеть так:

:host { 
  display: block; 
} 

:host([layout = "small"]) .form__item { 
  float: none;
  width: 100%;
} 

:host([layout = "large"]) .form__item { 
  display: table;
  float: left;
  width: 50%;   
}


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

Вывод


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

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

Комментарии (57)


  1. i360u
    04.05.2016 19:12
    +5

    Хватит уже ознакамливаться, пора использовать!
    Полифилл с таблицей поддержки: https://github.com/WebComponents/webcomponentsjs
    Описание создания компонента с использованием ES6: https://www.polymer-project.org/1.0/articles/es6.html + пример компонента на Polymer
    И хотелось бы добавить, что в отличие от использования Реакта (и прочего такого) для декомпозиции интерфейса, веб-компоненты — это стандарт. То есть в один прекрасный момент вы просто выпилите полифилл из проекта и все будет хорошо. А вот слезть с иглы в виде изоморфного Реакт-приложения будет ой как непросто...


    1. gearbox
      04.05.2016 21:40

      На typescript интереснее получается (там контроль типов можно использовать как контракты при обмене данными с сервером и сообщениями между элементами на странице), да и полимер не нужен, custom-elements вполне себе фреймворк, нарезаешь тегов под свой проект и половину программирования превращаешь в декларации. А реакт — да, другая философия. Все никак не соберусь потестить их вместе — реакт в custom-elements и наоборот, говорят уже допилили.


    1. ljonya
      05.05.2016 00:53

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


      1. i360u
        05.05.2016 05:52
        +3

        1. Не ковыряя руками DOM — вы лишаете себя многих чудесных возможностей и становитесь зависимы от фреймоврка. Мне удавалось многократно увиличивать производительность приложения переписывая компоненты с фреймворков на прямую работу с DOM (свой рендер для данных). Магические байндинги и обсерверы хороши только до тех пор, пока вы не выяснили как они работают. Потом вам становится проще писать такие штуки самому, чем бороться с особенностями чужой реализации (при этом я конечно противник "велосипедов"). В том-же Polymer, к примеру, нельзя использовать выражения в шаблонах, а это порой очень засоряет код самого компонента.
        2. Polymer отлично уживается с ванильными веб-компонентами в одном проекте, и однажды запрототипированные компоненты легко переписываются в любое время под любые задачи и с использованием любого языка, транспилируемого в JS, в том числе и с использованием статической типизации. Прелесть Polymer — в том, что он не навешивает на вас обязательств вечно с ним дружить. А вот React — делает это жестко, при этом зависимыми становятся и клиент, и сервер и даже ваша IDE (сейчас конечно все поддерживают jsx, но еще недавно это было проблемой. Ну и не все любят jsx, что вполне справедливо).
        3. Что именно вы подразумеваете, говоря о "чудесном воркфлоу" Реакта? Жизненный цикл компонентов? Работу с данными? Саму разработку? Лично я вижу в нем только одну чудесную вещь: возможности декомпозиции UI. Но этот вопрос еще чудеснее решается веб-компонентами. И декомпозировать UI (UI, модули, лейауты, секции) по моему опыту, вообще мало кто умеет. Обычно я встречаю жуткую кашу в jsx из JS, HTML, кастомных тегов, какого-нибудь бутсрапа с трехэтажными БЭМами и попытки из этого собрать страницу целиком в одном месте.


        1. Riim
          05.05.2016 12:29

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

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


          1. i360u
            05.05.2016 13:16

            Не согласен совершенно. Именно чем сложнее приложение, тем более справедливо то, что я говорю. И веб-компоненты вовсе не только для контролов, они хороши на любом уровне если приложение построено правильно. Просто компоненты должны быть четко разделены по классам задач, которые они решают: UI — для кнопочек, дропдаунов, слайдеров и т. д. (получают данные от родителя через параметы); модули — для блоков которые работают с логикой; лэйауты — для организации блоков интерфейса (расположение на экране, логика отображения); и секции — для роутинга и доступа к базовым параметрам приложения. Это конечно примерная схема, но лично я строю интерфейс приложения именно так. При этом, у вас есть возможность объединять все детали в один документ (что дает очень высокую скорость обращения и сокращает количество запросов к серверу) либо запрашивать отдельные тяжелые блоки как простой HTML с сервера и использовать их только при необходимости. Сборку модулей при этом разруливает сам браузер и вы получаете предельно гибкое и удобное для последующей поддержки решение. Ни один существующий фреймворк (не считая тех, что работают поверх веб-компонентов) вам этого не даст сделать так просто.


            1. Riim
              05.05.2016 13:43

              Это всё очевидно, данные то как биндить? Вариант с мешаниной калбеков не предлагать.


              1. i360u
                05.05.2016 14:19

                Никакой мешанины, все элемены (модули и их модели) созданы конструкторами соответсвующих классов, и узнают все необходимое друг о друге при создании. Модель знает о всех экземплярах (тех, что в данный момент отображены) связанного с ней компонента и вызывает его обновление через сеттеры или через специальный метод update(); Если компонентов несколько — обновляет все. Без лишних событий и проверок на правильного подписчика. Никаких колбэков, только прямой вызов метода. Колбек получается только один, нативный для веб-компонента, является частью его стандартного жизненного цикла, вызывает удаление связи с моделью при его удалении из DOM. А как вы думаете реализованы байндинги в фреймворках?


                1. Riim
                  05.05.2016 14:39
                  +1

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

                  то есть у вас модель знает о компоненте и сама обновляет его? Это как-то… кхм, необычно))


                  1. i360u
                    05.05.2016 14:54

                    Это круто, ибо просто и хорошо работает.


                    1. Riim
                      05.05.2016 15:54

                      Ok, но я бы не стал называть это моделью, можно было бы назвать въюмоделью, если бы не "Модель знает о всех экземплярах", так это скорее какой-то ComponentManager, но, опять же, создаётся впечатление, что у вас эта штука не только рассылает данные экземплярам, но ещё и хранит их. В общем, чудо-юдо какое-то)). Может тудулист для примера сбацаете?


                      1. Riim
                        05.05.2016 16:01

                        рассылает данные экземплярам, но ещё и хранит их

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


                      1. i360u
                        05.05.2016 16:14

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


                        1. Riim
                          05.05.2016 17:12

                          По вашей фразе:


                          вызывает его обновление через сеттеры или через специальный метод update()

                          создаётся впечатление, что речь не о подписке на модель, а модель сама знает о сеттерах и метод update()


                          Ладно, здесь вроде разобрались, ещё вопрос про это:


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

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


                          UPD: хотя понял, вместо одного model.on('change', ...) прийдётся делать множество подписок на изменения отдельных свойств (model.on('change:someprop', ...)), тут то первый раз и захочется биндингов, потому вы и не понимаете зачем они.


                          1. i360u
                            05.05.2016 18:07

                            Правильное впечатление, я говорил не о EBA.


                            myModel.update();

                            вызовет условный


                            myComponent.modelChangeHandler();

                            Потому, что в myModel есть свойство


                            myModel.bindedDomInstances = [myComponent, myComponent2, myComponent3];

                            При этом не нужны проверки подписки со стороны компонента, не нужно беспокоиться о безопасности эвентов, не нужны никакие on change и все то, о чем я писал изначально. Ничего, как вы видите, не обновляется без разбора. Я прекрасно знаю зачем нужен биндинг и отлично использую его. Но иногда мне нужен быстрый DOM, который должен в реальном времени изменение модели вызывать (это всякие редакторы таблиц, списков с перетаскиванием, и т. д.). свой рендер работает гораздо быстрее. И, конечно, это вовсе не потому, что создатели фреймворков — говнокодеры, а просто в сложных случаях не всегда годится тот подход, который реализован для случаев общих. Как еще объяснить я уж и не знаю...


                            1. Riim
                              05.05.2016 18:15

                              myModel.bindedDomInstances = [myComponent, myComponent2, myComponent3];

                              кто наполняет bindedDomInstances?


                              Ничего, как вы видите, не обновляется без разбора

                              как компонент узнаёт какие свойства модели, выводимые им, нужно обновить в dom-е?


                              1. i360u
                                05.05.2016 18:37

                                кто наполняет bindedDomInstances?

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

                                как компонент узнаёт какие свойства модели, выводимые им, нужно обновить в dom-е?

                                • Много способов, как вы сами понимаете. Можно через сеттер свойства модели реализовать, он ведь знает что именно записывает.

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


                                1. Riim
                                  05.05.2016 18:56

                                  Конструктор компонента

                                  тогда всё норм.


                                  через сеттер свойства модели

                                  так модель может узнать изменилась ли она и нужно ли генерить событие, но как компонент узнает, что изменилось в модели? Тут нужны либо события типа 'change:someprop', либо какая-то инфа в объекте события. Дальше либо много подписок и обработчиков, либо огромное ветвление в единственном обработчике. Дальше опять биндинги.


                                  1. i360u
                                    05.05.2016 19:04
                                    +1

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


                                    1. Riim
                                      05.05.2016 19:33

                                      Сеттер модели знает, как компонент узнаёт?
                                      Да.


                                      1. i360u
                                        05.05.2016 20:30
                                        +1

                                        Сорри, на этом пожалуй все, я бессилен.


                                        1. Riim
                                          05.05.2016 21:13

                                          Можно в виде кода попробовать разобраться. Как я понимаю у вас в упрощённом виде что-то вроде того: https://gist.github.com/Riim/6fe27c2ee69b13c9d1b41c48ff5ceabb
                                          Мне не нравится, что при записи в online произойдёт две лишние записи в innerHTML (https://gist.github.com/Riim/a3fab035befe77a6c90ab4cccfe17818#file-app-js-L44-L45).


              1. gearbox
                05.05.2016 16:10

                react, redux, immutable — внезапно это все можно завернуть в компонент и передавать параметры через аттрибуты и event-ы. У меня даже подключение к сокет-серверу через компонент идет. Компоненты общаются между собой event-ами. event-ы могут распространятся не только снизу-вверх, но и широковещательно для всех компонентов в room-е (да, сделал один раз такой компонент и использую) В общем обычное программирование, похоже на написание своего DSL.


            1. Virviil
              05.05.2016 15:19

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


              И отдельно, что касается "raw html"… Мне почему-то кажется, что html вообще должен умереть. С развитием SPA js всё теснее будет интегрироваться с html, и в какой то момент html превратится в xaml — этакое чудо, лежащее только в исходниках. И в этот момент с jsx переехать в новые реалии будет очень просто.


              1. i360u
                05.05.2016 16:01

                Реакт работает так, но несет в себе кучу избыточных сущностей для обслуживания самого себя. Я про то и говорю, что те задачи, которые решает Реакт можно решать без него ни капли от этого не страдая. С веб-компонентами вы можете захостить свое приложение на GitHub, сделать его презентацией используя vulcanize (один файл без внешних зависимостей, даже картинки в SVG будут внутри), собрать одну вьюху для Electron и для веб и тд. и тп. Вам не обязательно нужен сервер, вы можете делать приложения без бекэнда и использовать только API сторонних сервисов. И так Реакт уже не работает.


                А древовидный статический HTML — да, должен умереть. И в случае с веб-компонентами он используется, в основном, для определения кусков шаблона, т. е. вполне адекватно.


                1. Virviil
                  05.05.2016 16:46

                  Мне кажется, вы всё же немного путаете Реакт с его инфраструктурой. На сегодняшний день webpack-ом собирается react вместе с css в файл мой_апупенный_апп.js, который подключается в тег script и может "хостится на гитхабе". Туда же можно подключить и react-router (хотя это не обязательно). Туда же можно подключить flux библиотеку (хотя это тоже не обязательно). Конечно, этот js и весить будет опупенно, но разговор же не об этом.
                  Впрочем, что касается бэкэнда, то большинство js spa фреймворков его не требуют. Или Angular, Backbone, Knockout не могут работать только на чужих апи?.


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


                  1. i360u
                    05.05.2016 17:38

                    Подходы разняться тем, что в одном случае вам нужен Реакт, а в другом нет. Да, в итоге мы получаем примерно одно и то-же. Но без Реакта мы не имеем дополнительных зависимостей. Слезть с Реактовских "рельс" в сложном проекте, в определенный момент станет практически невозможно. В случае с изоморфным приложением — зависимость еще сильнее, и вам уже нужно заморачиваться с кучей вопросов на сервере (выдачу придется кэшировать, рендер в реальном времени будет очень медленным). А веб-компоненты — это стандарт, который скоро будет поддерживаться всеми браузерами. И собирать компоненты будет браузер, нативно, и соответсвенно максимально быстро и оптимизированно, не в JS рантайме. Так если нет разницы в результате (условно говоря), зачем увеличивать технический долг?


                    1. Riim
                      05.05.2016 18:06

                      реальном времени будет очень медленным

                      как то замеряли это?


                      1. i360u
                        05.05.2016 18:13

                        Да, фигачили как-то приложение в Реакте и потом долго придумывали как реализовать кэш с Redis. На довольно мощном железе тормозило (вывод каталога по фильтрам). Бекэндом не я лично занимался, но ребята неглупые вроде.


                        1. Riim
                          05.05.2016 18:19

                          Какая нагрузка была? Сколько рендеров, скажем, в минуту?


                          1. i360u
                            05.05.2016 18:53
                            +1

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


                            1. Riim
                              06.05.2016 14:20

                              Кстати, с неделю назад 2гис запустил новый проект http://skver.2gis.ru/, сделанный как раз на реакте с изоморфностью. Пообщался с одним из разработчиков, он говорит, что одна нода спокойно держит всю нагрузку, она (нагрузка) по сравнению с основным проектом конечно небольшая совсем, но при росте ещё можно приручивать кеш и масштабировать рендеринг на несколько нод. Так что не так уж всё и плохо с реактом как вы говорите, в теории, действительно, реакт должен рендерить медленнее классических шаблонизаторов, но в прямых руках он вполне годен для таких проектов.


                              1. nuit
                                06.05.2016 15:47
                                +2

                                Queueing 3.89?ms
                                Stalled 7.71?ms
                                DNS Lookup 2.18?ms
                                Initial connection 10.57?ms
                                SSL 8.08?ms
                                Request/Response TIME
                                Request sent 0.20?ms
                                Waiting (TTFB) 4.09?s
                                Content Download 17.53?ms


                                Waiting (TTFB) 4.09?s!!! Вжопу такое SSR :)


                                1. Riim
                                  06.05.2016 16:12

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


                                  1. nuit
                                    06.05.2016 16:27

                                    В жаваскрипт комьюнити всё же договорились использовать слово «универсальные» вместо «изоморфные» :)

                                    Я конечно люблю реакт, и достаточно плохо отношусь к спеке вебкомпонент :) Но я ещё ниразу не видел чтобы кто-то нормально реализовал SSR на реакте так чтобы это было хотябы на приемлемом уровне с точки зрения скорости, ну и особенно когда дело доходит до UX. Лет пять назад когда для решения этой же проблемы тупо писали два куска кода, один для генерации на сервере, другой на клиенте для progressive enhancement, всё было гораздо лучше. И пока с сервера приходил тяжёлый кусок жаваскрипта, с помощью маленького скрипта внедрёного прям на страницу, контролы собирали эвенты, демонстрировали какой-то фидбэк пользователю. Сейчас же все начали делать полное гавно в попытках писать универсальный код, который в итоге ещё и сложнее реализовать, тк накладывает кучу ограничений на жаваскрипт код.


      1. i360u
        05.05.2016 06:01
        +3

        И еще забыл добавить насколько "чудесны" реактовские роутеры с этими их линками...


        1. Virviil
          05.05.2016 15:24

          react-router не имеет отношения к react в плане UI. Вы можете использовать react без роутеров. Или использовать react-router вместе с webcomponents. Или использовать react с любым роутером, который вы планируете использовать с webcomponents.
          Да и в принципе, если использовать какой-нибудь redux можно не использовать роутинг вообще.


          1. i360u
            05.05.2016 16:29

            Ну да, все верно, но "осадочек то остался" =)


  1. gearbox
    04.05.2016 21:36
    +5

    Поддержу предыдущего оратора + добавлю — в статье ничего не говорится о webcomponents, кроме заголовка. Три экрана рассуждений о стилях — и ни одного упоминания о том как они внезапно станут тегом subscribe-form. Автор — оденьте шляпу нуба и перечитайте статью — ничего не понятно. (лично мне не надо объяснять — я эту технологию активно использую)


    1. gearbox
      04.05.2016 21:42

      хех, перевод же.


  1. Minoru
    05.05.2016 11:49

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

    Хотелось бы узнать, что это за возможности


  1. DenimTornado
    05.05.2016 12:02

    Эх, ещё бы нативную возможность передачи модели внутрь компонента… Нативная шаблонизация. Было бы очень неплохо.


    1. i360u
      05.05.2016 13:34

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


      1. Riim
        05.05.2016 13:44

        Через параметры только строки/числа, ссылосный тип, как в реакте, уже не передать, прийдётся вызывать метод, что не так удобно.


        1. megaalli66
          05.05.2016 14:22

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


          1. Riim
            05.05.2016 14:43

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


            1. megaalli66
              05.05.2016 16:23

              Для просто передать, это избыточное решение, согласен.

              Но вот когда компонентов становится много и появляется лапша между событиями, методами и callback в них, становится каша. Со временем становится понятно, что с DOM-объектом, надо общаться именно как с DOM-объектом, т.е. используя параметры и события. И custom-element является частью именно DOM. Мухи отдельно, котлеты съелиотдельно.

              Но это в ситуации с нативными веб-компонентами.


              1. DenimTornado
                05.05.2016 21:31

                Ох ты ж, блин, объясняю, я бы хотел позвожность сделать так:

                <author name="John" surname="Daw"></author>
                

                А если уж была бы возможность хотя бы итерации… Эх.


                1. kemply
                  05.05.2016 23:39

                  Интересно узнать: а для чего вам такие компоненты?


                  1. i360u
                    06.05.2016 07:13

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


                1. i360u
                  06.05.2016 07:16

                  Да, вы можете сделать именно так. С одним нюансом:


                  <article-author name="John" surname="Daw"></article-author>

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


                1. dimon_durak
                  06.05.2016 15:24

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

                  Можно конфигурировать элементы атрибутами, причём значения могут быть числом, строкой, и даже объектом или массивом. Булевые значения тоже, они определяются наличием атрибута.

                  И да, итерации тоже есть


  1. megaalli66
    05.05.2016 12:32
    +2

    В текущее время с WebComponents(речь про нативные) есть следующие проблемы.

    1. Не совсем стабильная спецификация. Это про slot-based ShadowDOM или как по другому вроде называется ShadowDOM v1. Поддержки slot-based еще нигде нет, но заявлен на нее переход. Что со старым вариантом будет, мне неизвестно. Но думаю тоже самое, что и с CSS псевдоэлементами, которые работают с ShadowDOM => т.е. deprecated.
    2. Достаточно плохая производительность ShadowDOM v0, что и стало поводом для создания slot-based ShadowDOM (v1)
    3. Как уже писал выше, есть серьезные проблемы с CSS и ShadowDOM в chromium-based браузерах. Причем со скоростью отрисовки.
    4. В текущей реализации в chromium-based браузерах, есть ощущение того, что ShadowDOM было сделано костылем поверх текущей реализации DOM. С другой стороны, благодаря этому возможно сделать аналог обычной html-таблицы на веб-компонентах. Но это если делать сложную структуру из веб-компонентов. В 90% ситуации вы с этим не столкнетесь.

    В общем, пока стоит использовать полифилл, т.к. и спецификация нестабильна и реализации не без проблем.

    Но при этом всем WebComponents это реально удобная вещь.


  1. kemply
    05.05.2016 13:59

    Всё равно использовать эти компоненты еще слишком рано. Считаю, что кроссбраузерность важнее всего


  1. M-A-XG
    07.05.2016 22:25

    >.form__item

    В чем соль двойного подчеркивания?


    1. web_for_mass
      07.05.2016 22:30
      +1

      BEM-naming, подробнее про это можешь почитать здесь «Соглашение по именованию»


      1. M-A-XG
        08.05.2016 11:35
        -1

        Тогда у меня свой стиль BEM :)