[Перевод] Внедрение компонентого подхода в вебе: обзор веб-компонент
Четыре из пяти самых запрашиваемых новых платформенных возможностей Edge на User Voice (Shadow DOM, Template, Custom Elements, HTML Imports) относятся к семейству API, называемых веб-компонентами (Web Components). В этой статье мы хотим рассказать о веб-компонентах и нашем взгляде на них, некоторой внутренней кухне, для тех, кто еще с ними не знаком, а также порассуждать на тему того, куда все это может эволюционировать в будущем. Это довольно-таки длинный рассказ, поэтому откиньтесь назад, возьмите кофе (или не кофеиновый напиток) и начинайте читать.
Содержание:
- Внедрение компонент: старая практика проектирования, ставшая новой для веба
- Как разбивать на компоненты
- Это все не в первый раз: предыдущие подходы к внедрению компонент
- Современные веб-компоненты
- Веб-компоненты: следующее поколение
Внедрение компонент: старая практика проектирования, ставшая новой для веба
Современные веб-приложения столь же сложны, как и любые другие программные приложения, и зачастую создаются несколькими людьми, объединяющими усилия для создания финального продукта. В таких условиях, чтобы повысить эффективность, естественно искать правильные способы разделения работы на участки с минимальными пересечениями между людьми и подсистемами. Внедрение компонентного подхода (в целом) — это то, как обычно решается такая задача. Любая компонентная система должна уменьшать общую сложность через предоставление изоляции, или естественных барьеров, скрывающих сложность одних систем от других. Хорошая изоляция также облегчает повторное использование и внедрение сервисных парадигм.
Изначально сложность веб-приложений в основном регулировалась со стороны сервера за счет разделения приложения на отдельные страницы, что требовало от пользователя соответствующим образом переходить в браузере с одной страницы на другую. С внедрением AJAX и связанных технологий разработчики смогли отказаться от потребности делать «переходы» между разными страницами веб-приложения. Для типичных сценариев вроде чтения почты или новостей ожидания пользователей изменились. К примеру, после логина в почту, вы можете «пользоваться почтовым приложением» с одного и того же адреса (URL) и находится на этой странице целый день (т.н. Single-Page Applications, SPA). Логика клиентских веб-приложений в таких ситуациях существенно усложняется, иногда она даже становится сложнее, чем на серверной стороне. Возможным разрешением данной сложности может являться дальнейшее разделение на компоненты и изоляция логики внутри одной страницы или документа.
Цель веб-компонент в уменьшении сложности за счет изоляции связанных групп кода на HTML, CSS и JavaScript для выполнения общей функциональности в пределах контекста одной страницы.
Как разбивать на компоненты?
Так как веб-компоненты должны связать воедино HTML, CSS и JavaScript, необходимо учитывать существующие модели изоляции, присущие каждой из технологий, так как они влияют на сценарии и целостность веб-компонент. Эти независимые модели изоляции включают:
- Изоляция стилей в CSS
- JavaScript и области видимости (замыкания)
- Изоляция глобального объекта
- Инкапсуляция элементов (iframe)
Изоляция стилей в CSS
В рамках сегодняшней платформы не существует идеального и естественного способа разбить CSS на компоненты (хотя инструменты вроде Sass могут существенно помочь). Компонентная модель должна предлагать механизм для изоляции одного подмножества CSS от другого так, что правила не будут влиять друг на друга. К тому же, стили компоненты должны применяться только к непосредственным частям компоненты и более ни к чему другому. Легче сказать, чем сделать!
Внутри таблиц стилей CSS-правила применяются к документу, используя селекторы. Селекторы всегда рассматриваются как потенциально применимые ко всему документу, поэтому их область применения, в сущности, глобальная. Глобальное применение приводит к реальным конфликтам, когда несколько человек, работающих над проектом, смешивают вместе свои CSS-файлы. C пересечениями и повторениями селекторов можно бороться в четком порядке (например, каскады, специфичность, порядок следования исходников) для разрешения конфликтов, однако, такие действия, вполне вероятно, — совсем не то, чего хотели разработчики. Есть много потенциальных способов решения этой проблемы. Простое решение — перенести элементы и связанные стили, участвующие в формировании компоненты из основного документа в другой документ (теневой документ) так, что они больше не будут «реагировать» на чужие селекторы. Это приводит ко второй проблеме: теперь, когда мы их разграничили, как некоторый стиль может пересечь границу (для управления снаружи компоненты)? Очевидное возможное решение — это явно использовать JavaScript, но это выглядит как-то ужасно: полагаться на JavaScript для передачи стилей через границу, что кажется скорее пробелом в CSS.
Чтобы передать стили через границу компоненты эффективным образом и при этом защитить структуру компоненты (например, разрешить свободу изменения структуры без влияния стилей), существует два общих подхода, к которым многие склоняются: «частичная» стилизация с использованием псевдо-элементов и кастомные свойства (ранее известные как «переменные» CSS). Какое-то время также рассматривался супер-мощный кросс-граничный селектор '>>>' (определен в CSS Scoping), но сегодня он общепризнан не самой удачной идеей, так как легко нарушает изоляцию компонент.
Частичная стилизация позволит авторам компоненты создавать собственные псевдо-элементы для стилизации, таким образом, выставляя наружу внешнему миру только часть своей внутренней структуры. Это похоже на модель, которую браузеры используют для выставления «частей» нативных элементов управления. Для целостности данного сценария авторам также понадобится некоторый способ ограничения набора стилей, которые могут применять к псевдо-элементу. Дополнительное исследование этой «частичной модели», базирующейся на пcевдо-элементах, может привести к появлению удобных стилистических примитивов, хотя проработка деталей еще потребует усилий. Дальнейшая работа над частичной моделью также должна рационализировать стилизацию родных элементов управления в браузерах (область, которая явно нуждается во внимании).
Кастомные свойства позволят авторам описывать значения стилей, которые они хотят повторно использовать в таблицах стилей (определяются как собственные имена свойств с двойным тире в качестве префикса). Кастомные свойства наследуются через под-дерево документа, позволяя селекторам переопределять значение кастомного свойства для конкретного под-дерева без затрагивания других под-деревьев. Кастомные свойства также смогут наследоваться через границы компонент, предоставляя элегантный механизм стилизации компонент, который при этом избегает раскрытия внутренней структурной природы компоненты. Кастомные свойства оценивались при разработке разных компонентных фреймворков в Google и, по отчетам, позволяют покрыть большинство потребностей стилизации.
Из всех рассматриваемых на сегодня подходов для стилизации будущая «частичная» модель и текущая спецификация кастомных свойств, кажется, имеют наибольшие шансы реализации. Мы рассматриваем кастомные свойства в качестве нового ключевого члена семейства спецификаций веб-компонент.
Другие подходы к изоляции CSS стилей
Для полноты картины, области видимости и изоляция CSS — это не такая черно-белая область, как могло показаться выше. На самом деле, несколько прошлых и текущих подходов предлагают варианты ограничения области применения и изоляции с различной применимостью к веб-компонентам.
CSS предлагает некоторые ограниченные формы изоляции селекторов в специфичных сценариях. Например, правило @media группирует набор селекторов вместе и применяет их при наступлении условий, соответствующих медиа-контексту (например, размер или разрешение вьюпорта, или медиа-тип — печать и т.п.); правило @page определяет некоторые стили, которые применимы только в контексте печати; правило @supports объединяет вместе селекторы для применения только, когда реализована поддержка специфичной CSS-функциональности — новая форма определения наличия функциональности в CSS); предложенное правило @document группирует селекторы для применения только тогда, когда документ, в котором загружены стили, соответствует условиям.
Области видимости в CSS (изначально написанные как часть работы над веб-компонентами) предлагают способ ограничивать применимость CSS-селекторов внутри одного HTML-документа. Спецификация вводит новое правило @scope, которое позволяет селектору определить корень (и) области применения и далее приводит к тому, что применение всех селекторов внутри правила @scope будет работать только в поддереве этого корны (а не на всем документе). Спецификация позволяет указывать корень области декларативно в HTML (например, предложен