[Разработка веб-сайтов, JavaScript] Веб-компоненты в реальном мире (часть 2)
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Прошло больше года с моей публикации "Веб-компоненты в реальном мире" и у меня накопились новые наблюдения, что ещё не так с этой технологией. Возможно, эти моменты позволят кому-то избежать тупикового пути для своих проектов.
Photo by Brandon Molitwenik on Unsplash
Сломанный HTML
В HTML есть много полезных возможностей, которые позволяют реализовывать функциональность без использования JavaScript. Одной из таких фич является возможность отправки формы при нажатии на клавишу Enter в любом поле ввода. Вот пример:
<form>
<label>First name: <input type="text"></label>
<label>Last name: <input type="text"></label>
<button>Send!</button>
</form>
Вводим текст, нажимаем Enter, данные отправляются на сервер, никакого JavaScript. При желании можно избежать перезагрузки страницы, и сделать отправку данных через AJAX, но и в этом случае количество JS будет минимальным.
А теперь попробуем заменить обычную кнопку на веб-компонент:
<form>
<label>First name: <input type="text"></label>
<label>Last name: <input type="text"></label>
<my-button>Send!</my-button>
</form>
Веб-компонент my-button внутри себя содержит всё ту же кнопку, визуально никаких отличий нет. А вот отправка формы по нажатию Enter сломалась! Вот демо, можете убедиться в этом сами.
В чем причина такого поведения? Это недоработка спецификации веб-компонентов, вот тикет. В библиотеках разработчики обходят эту проблему с помощью вот такого костыля, например. Сам код выглядит не очень страшно, но давайте на секунду задумаемся: мы пишем кастомный Javascript, чтобы починить поведение, которое сломал веб-стандарт. На всякий случай напомню, что спецификации веб-компонентов уже 8 лет и изо всех утюгов трубят, что она уже production-ready.
Но это ещё не всё, что умудрились сломать в веб-компонентах. В HTML есть такая фича, автоматический фокус поля ввода при нажатии на соседний label. Очень удобно, не обязательно целиться в маленький квадрат, можно нажать на текст рядом. Но не в случае веб-компонентов! Вот пример:
<label>First name: <input type="text"></label>
<label>Last name: <my-input></label>
На демо видно, что обычный тэг input можно выделить нажатием на "First name", а вот нажатие на "Last name" веб-компонент выделить не может. Проблема! На эту тему есть открытый тикет с последним комментарием 2 года назад, так что скорого разрешения тут ждать не стоит. У разработчиков пока есть только один способ – объединить label и input в один компонент. А как быть, если дизайн этого не позволяет? Тут два варианта, либо уговаривать дизайнеров придумать что-то совместимое с веб-компонентами, либо отказаться от веб-компонентов в своем проекте (по крайней мере, от ShadowDOM).
CSP
В своё время нашумел "Рассказ о том, как я ворую номера кредиток и пароли у посетителей ваших сайтов". В качестве одной из мер защиты там упоминается CSP – возможность указать белый список доменов, на которые разрешено делать запросы с вашей страницы. Одним из побочных эффектов внедрения CSP является невозможность использовать <style></style> тэги, только внешние файлы через <link rel="stylesheet"> (конечно, можно разрешить style-тэги обратно, через директиву 'unsafe-inline', но как видно из её названия, это будет ослабление вашей защиты).
При чем здесь веб-компоненты? Дело в том, что содержимое ShadowDOM полностью изолированно от внешних стилей, загруженных на страницу, поэтому для стилизации внутри ShadowDOM обычно используются style-тэги, что противоречит CSP. Два самых популярных веб-компонент фреймворка имеют с этим проблемы: Stencil (тикет) и LitElement (тикет).
Свет в конце туннеля есть – планируется новое Constructable Stylesheets API, которое позволит создавать стили для ShadowDOM в безопасной форме без необходимости в unsafe-inline. А пока разработчикам придется делать выбор – либо CSP, либо веб-компоненты.
Lifecycle-хаос
В хорошей архитектуре компоненты должны выполнять роль кирпичиков, из которых собирается большой проект. Например, мы можем получить такую комбинацию (по аналогии с material-web-components):
<my-menu>
<my-menu-item />
<my-menu-item />
</my-menu>
В этой ситуации два веб-компонента должны взаимодействовать друг с другом. Обычно это делается в connectedCallback. Веб-компонент подключается в DOM и осматривается вокруг. В случае подобных композитных компонентов может иметь значение, на каком компоненте этот метод вызовется первым. Проведем тест:
class MyMenu extends HTMLElement {
connectedCallback() {
console.log('my menu')
}
}
class MyMenuItem extends HTMLElement {
connectedCallback() {
console.log('my menu item')
}
}
// регистрация
customElements.define('my-menu', MyMenu)
customElements.define('my-menu-item', MyMenuItem)
Запускаем демо, смотрим в консоль и видим:
"my menu"
"my menu item"
"my menu item"
Можно предположить что connectedCallback вызывается на родительском элементе, потом на дочерних. Звучит логично, почему нет. А что, если мы сделаем маленькое изменение и откроем второе демо:
"my menu item"
"my menu item"
"my menu"
Как это получилось? Почему my-menu теперь опаздывает? В HTML изменений нет, но мы переставили эти две строки местами
// было
customElements.define('my-menu', MyMenu)
customElements.define('my-menu-item', MyMenuItem)
// стало
customElements.define('my-menu-item', MyMenuItem)
customElements.define('my-menu', MyMenu)
Оказывается, порядок регистрации элементов влияет на порядок вызова connectedCallback. В практическом смысле это означает то, что мы не можем знать порядок вызова методов, и наш код должен быть готов обработать оба варианта. С вариантом "нас вызвали слишком рано" все просто, добавляем window.setTimeout делаем нашу инициализацию попозже. В случае "нас вызвали слишком поздно" ситуация хуже, мы уже не сможем отменить начатые операции. Поэтому на веб-компонентах не получится сделать нормально работающий компонент спойлера
Пример спойлера
SPL
Веб-компонент не сможет остановить рендеринг внутренностей спойлера. К моменту активации компонента внутренние картинки уже начнут загружаться и потреблять ваш траффик, даже если вы не хотели открывать этот спойлер.
Выводы
В веб-компонентах повсюду раскиданы грабли, грамотно присыпанные маркетингом от Гугла. В стандарте еще много неразрешенных вопросов, которые могут оказаться непреодолимым препятствием для ваших проектов. Было бы полезно знать о потенциальных граблях заранее, чтобы принять более взвешенное решение, использовать ли веб-компоненты и фреймворки на их основе, или остаться с простым старым подходом на HTML/JS/CSS. Надеюсь, эта статья была полезной, спасибо за внимание!
===========
Источник:
habr.com
===========
Похожие новости:
- [JavaScript] LINQ на JavaScript для самых маленьких
- [Разработка веб-сайтов, JavaScript, Программирование, Node.JS] Краткое руководство по Node.js для начинающих (SPA, PWA, mobile-first)
- [Разработка веб-сайтов, JavaScript, Java, VueJS] Знакомство с Vuecket
- [JavaScript, Node.JS, ReactJS, VueJS] Что, черт возьми, такое гидратация и регидратация? (перевод)
- [Разработка веб-сайтов, Программирование, ReactJS, Управление проектами] Как не закопаться в рефакторинге на фронте. Советы новичку
- [Разработка веб-сайтов, JavaScript, Программирование] JavaScript: 250+ практических вопроса (список + викторина + бонус)
- [Разработка веб-сайтов, JavaScript, Программирование] Webpack: руководство для начинающих (перевод)
- [Разработка веб-сайтов, JavaScript] Влияние service worker'ов на web-приложения
- [JavaScript, Java, Big Data, Data Engineering] В диких условиях. Итоги проектов Школы программистов в эпоху самоизоляции
- [Разработка веб-сайтов, PHP, Проектирование и рефакторинг] Сущности (entities) и сервисы (services) как основа распределенной логики для MVC шаблона проектирования
Теги для поиска: #_razrabotka_vebsajtov (Разработка веб-сайтов), #_javascript, #_webcomponents, #_angular, #_javascript, #_w3c, #_css, #_a11y, #_razrabotka_vebsajtov (
Разработка веб-сайтов
), #_javascript
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 14:32
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Прошло больше года с моей публикации "Веб-компоненты в реальном мире" и у меня накопились новые наблюдения, что ещё не так с этой технологией. Возможно, эти моменты позволят кому-то избежать тупикового пути для своих проектов. Photo by Brandon Molitwenik on Unsplash Сломанный HTML В HTML есть много полезных возможностей, которые позволяют реализовывать функциональность без использования JavaScript. Одной из таких фич является возможность отправки формы при нажатии на клавишу Enter в любом поле ввода. Вот пример: <form>
<label>First name: <input type="text"></label> <label>Last name: <input type="text"></label> <button>Send!</button> </form> Вводим текст, нажимаем Enter, данные отправляются на сервер, никакого JavaScript. При желании можно избежать перезагрузки страницы, и сделать отправку данных через AJAX, но и в этом случае количество JS будет минимальным. А теперь попробуем заменить обычную кнопку на веб-компонент: <form>
<label>First name: <input type="text"></label> <label>Last name: <input type="text"></label> <my-button>Send!</my-button> </form> Веб-компонент my-button внутри себя содержит всё ту же кнопку, визуально никаких отличий нет. А вот отправка формы по нажатию Enter сломалась! Вот демо, можете убедиться в этом сами. В чем причина такого поведения? Это недоработка спецификации веб-компонентов, вот тикет. В библиотеках разработчики обходят эту проблему с помощью вот такого костыля, например. Сам код выглядит не очень страшно, но давайте на секунду задумаемся: мы пишем кастомный Javascript, чтобы починить поведение, которое сломал веб-стандарт. На всякий случай напомню, что спецификации веб-компонентов уже 8 лет и изо всех утюгов трубят, что она уже production-ready. Но это ещё не всё, что умудрились сломать в веб-компонентах. В HTML есть такая фича, автоматический фокус поля ввода при нажатии на соседний label. Очень удобно, не обязательно целиться в маленький квадрат, можно нажать на текст рядом. Но не в случае веб-компонентов! Вот пример: <label>First name: <input type="text"></label>
<label>Last name: <my-input></label> На демо видно, что обычный тэг input можно выделить нажатием на "First name", а вот нажатие на "Last name" веб-компонент выделить не может. Проблема! На эту тему есть открытый тикет с последним комментарием 2 года назад, так что скорого разрешения тут ждать не стоит. У разработчиков пока есть только один способ – объединить label и input в один компонент. А как быть, если дизайн этого не позволяет? Тут два варианта, либо уговаривать дизайнеров придумать что-то совместимое с веб-компонентами, либо отказаться от веб-компонентов в своем проекте (по крайней мере, от ShadowDOM). CSP В своё время нашумел "Рассказ о том, как я ворую номера кредиток и пароли у посетителей ваших сайтов". В качестве одной из мер защиты там упоминается CSP – возможность указать белый список доменов, на которые разрешено делать запросы с вашей страницы. Одним из побочных эффектов внедрения CSP является невозможность использовать <style></style> тэги, только внешние файлы через <link rel="stylesheet"> (конечно, можно разрешить style-тэги обратно, через директиву 'unsafe-inline', но как видно из её названия, это будет ослабление вашей защиты). При чем здесь веб-компоненты? Дело в том, что содержимое ShadowDOM полностью изолированно от внешних стилей, загруженных на страницу, поэтому для стилизации внутри ShadowDOM обычно используются style-тэги, что противоречит CSP. Два самых популярных веб-компонент фреймворка имеют с этим проблемы: Stencil (тикет) и LitElement (тикет). Свет в конце туннеля есть – планируется новое Constructable Stylesheets API, которое позволит создавать стили для ShadowDOM в безопасной форме без необходимости в unsafe-inline. А пока разработчикам придется делать выбор – либо CSP, либо веб-компоненты. Lifecycle-хаос В хорошей архитектуре компоненты должны выполнять роль кирпичиков, из которых собирается большой проект. Например, мы можем получить такую комбинацию (по аналогии с material-web-components): <my-menu>
<my-menu-item /> <my-menu-item /> </my-menu> В этой ситуации два веб-компонента должны взаимодействовать друг с другом. Обычно это делается в connectedCallback. Веб-компонент подключается в DOM и осматривается вокруг. В случае подобных композитных компонентов может иметь значение, на каком компоненте этот метод вызовется первым. Проведем тест: class MyMenu extends HTMLElement {
connectedCallback() { console.log('my menu') } } class MyMenuItem extends HTMLElement { connectedCallback() { console.log('my menu item') } } // регистрация customElements.define('my-menu', MyMenu) customElements.define('my-menu-item', MyMenuItem) Запускаем демо, смотрим в консоль и видим: "my menu"
"my menu item" "my menu item" Можно предположить что connectedCallback вызывается на родительском элементе, потом на дочерних. Звучит логично, почему нет. А что, если мы сделаем маленькое изменение и откроем второе демо: "my menu item"
"my menu item" "my menu" Как это получилось? Почему my-menu теперь опаздывает? В HTML изменений нет, но мы переставили эти две строки местами // было
customElements.define('my-menu', MyMenu) customElements.define('my-menu-item', MyMenuItem) // стало customElements.define('my-menu-item', MyMenuItem) customElements.define('my-menu', MyMenu) Оказывается, порядок регистрации элементов влияет на порядок вызова connectedCallback. В практическом смысле это означает то, что мы не можем знать порядок вызова методов, и наш код должен быть готов обработать оба варианта. С вариантом "нас вызвали слишком рано" все просто, добавляем window.setTimeout делаем нашу инициализацию попозже. В случае "нас вызвали слишком поздно" ситуация хуже, мы уже не сможем отменить начатые операции. Поэтому на веб-компонентах не получится сделать нормально работающий компонент спойлера Пример спойлераSPLВеб-компонент не сможет остановить рендеринг внутренностей спойлера. К моменту активации компонента внутренние картинки уже начнут загружаться и потреблять ваш траффик, даже если вы не хотели открывать этот спойлер. Выводы В веб-компонентах повсюду раскиданы грабли, грамотно присыпанные маркетингом от Гугла. В стандарте еще много неразрешенных вопросов, которые могут оказаться непреодолимым препятствием для ваших проектов. Было бы полезно знать о потенциальных граблях заранее, чтобы принять более взвешенное решение, использовать ли веб-компоненты и фреймворки на их основе, или остаться с простым старым подходом на HTML/JS/CSS. Надеюсь, эта статья была полезной, спасибо за внимание! =========== Источник: habr.com =========== Похожие новости:
Разработка веб-сайтов ), #_javascript |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 14:32
Часовой пояс: UTC + 5