Понятно и просто про WEB-компоненты и Polymer
Кто я
Я — Александр Кашеверов. По образованию — магистр радиофизики. По профессии — веб-разработчик, работаю в компании DataArt с 2011 года, с 2009 увлекаюсь IT и веб-технологиями.О чем статья, коротко
Рассмотрим, что такое web-components и polymer. Немного поразмышляем на тему развития веба. Посмотрим на технические детали, примеры, поддержку браузерами, тестирование. Коротко, понятно, по делу. С картинками.Вступление
Веб постоянно развивается. Технологии были придуманы и внедрены, исходя из потребностей, актуальных на момент создания. Десять лет назад невозможно было сделать то, что мы реализуем сейчас, и сложно представить, что будет еще через 10 лет.
Бизнес требует создания крупных и сложных программных веб-продуктов с богатой функциональностью, красотой, высокой производительностью. Такие решения нетривиальны сами по себе, так еще и накладывается специфичность веб-технологий. Зачастую, чтобы уменьшить сложность продукта, его разделяют на множество более простых частей. Такой компонентный подход уменьшает хаос, улучшает структуру, понимаемость, увеличивает эффективность командной работы.
Для уменьшения головной боли хорошо бы, если в контексте веб:
- CSS не пересекался.
- Области видимости JS не пересекались.
- HTML был понятным и читаемым, никаких лишних элементов.
В настоящее время это не совсем так. Относительно JavaScript: приходится следить, чтобы он не работал с global scope и разные компоненты случайно не взаимодействовали друг с другом. В CSS нет и не было инкапсуляции, приходится придумывать методологии вроде MCSS и bem, чтобы ничего лишний раз не сломалось. И наконец, в HTML можно увидеть множество лишних элементов на странице, например, даже сейчас в почте gmail…
Запутанно… Не правда ли?
Фреймворки в той или иной степени внедряют компонентизацию и стараются решить эти задачи. Однако, они так же построены на всё тех же HTML, CSS, JavaScript.
Web Components — коротко
Веб медленно, но верно движется к компонентизации — это естественный процесс. Сложное можно упростить, разбив на части. Параллельно развитию фреймворков идет работа и на более низком уровне. Набирают популярность веб-компоненты. Это реализация идеи компонентизации на уровне браузера.
История веб-компонентов началась в 2011 году (первое упоминание на github). Кратко — что это:
- Custom Elements — создание своих html-элементов, дополнение существующих.
- Shadow DOM — инкапсуляция логики и стилей.
- Templates — шаблоны на уровне браузера!
- HTML imports — вместо подключения отдельно разных файлов [css, js, ...] можно подключать один HTML-документ, включающий все остальные файлы.
При использовании этих четырех технологий вместе, получаются автономные пеереиспользуемые блоки — веб-компоненты.
На самом деле, некое подобие веб-компонентов уже было создано давно. Простейший пример — элемент <select>
. Для него есть отдельный тег. Взаимодействуя с элементом, появляется выпадающий список и эта логика скрыта от нас, к тому же у него есть свои собственные стили.
<select>
<option value="Yandex">Yandex</option>
<option value="Google" selected>Google</option>
<option value="Yahoo">Yahoo</option>
</select>
Так же и с HTML5 элементами <video>
или <audio>
.
В этом и есть суть web-компонентов — создание простых и понятных независимых элементов со скрытой логикой, стилями.
Наверняка многие подключали в проект Bootstrap — для этого нужно отдельно прописать подгрузку стилей и скриптов. С компонентами это можно было бы сделать проще.
<link rel="import" href="bootstrap.html">
Web Components — не фреймворк. Это набор технологий, реализованных на уровне браузера.
Web Components — поддержка браузерами & polyfills
На данный момент (ноябрь 2015) три из чеырех технологий находятся в стадии «Working Draft» на W3C.
Так выглядит ситуация на данный момент (ноябрь 2015):
Так как веб-компоненты в перспективе имеют высокую ценность, но, как обычно, не поддерживаются всеми браузерами, создаются способы улучшить поддержку. Так появились полифиллы.
С их помощью, поддержка браузерами уже получше.
На web-странце, полифиллы подключается стандартно в head (до всех скриптов, которые используют веб-компоненты):
<script src="path/webcomponents.js"></script>
Web Components — ссылки
Polymer
Тем временем, Google всё упрощает и развивает. Работа началась осенью 2012 года, судя по истории коммитов на github. Они взяли веб-компоненты, полифилы и создали еще одну надстройку.
Цель Polymer — упростить создание качественных веб-приложений (цитата product manager с конференции Google IO).
Polymer — коротко
Библиотека представляет собой веб-компоненты в основе, полифилы для поддержки старых браузеров, это всё обернуто в целостную более удобную систему с добавлением сахара.
Сехматически это выглядит так:
Google создал набор готовых компонент и разделил их на логические части:
Основные строительные блоки |
<iron-icon>, <iron-input>, <iron-list>, … |
|
Элементы на основе iron-elements и material design |
<paper-input>, <paper-button>, <paper-tooltip>, ... |
|
Коллекция web-компонентов, использующих различные API Google |
<google-analytics>, <google-chart>, <google-map>, … |
|
Элементы, специфичные для интернет-коммерции |
<gold-cc-input>, <gold-phone-input>, <gold-email-input>, ... |
|
Элементы для создания анимаций |
<neon-animation> |
|
Элементы, помогающие создать из веб-страницы настоящее приложение |
<platinum-bluetooth-device>, <platinum-sw-cache>, <platinum-push-messaging>, ... |
|
Элементы-обертки других библиотек/приложений |
<marked-element> |
Можно заметить, что постоянно фигурирует слово «элемент». Google считает, что для всего можно сделать элемент. «There is an element for that» («для этого есть элемент») — звучит, как слоган в докладах Google IO 2015.
Да, даже для ajax запроса есть элемент. Выглядит так:
<iron-ajax url="some url" handle-as="json" on-response="onResponse"></iron-ajax>
При создании приложений мы сталкиваемся с примерно одинаковыми задачами, и Google предлагает набор готовых строительных блоков для этого. С какой бы проблемой мы не столкнулись — для ее решения есть элемент. «There is an element for that».
Создан каталог готовых Polymer-компонентов.
Polymer — не фреймворк, как и Web Components — не фреймворк. Polymer — это обертка и сахар. Я бы идейно ее сравнил с jQuery. jQuery создана для работы с DOM, а Polymer — для работы с Web Components.
Polymer — тестируемость
Да, он тестируемый, и для этого создана отдельная утилита web-component-tester. Понятное описание.
Пробовал. Работает (при установке могут возникнуть проблемы с Java и Selenium).
Несколько шагов, чтобы заработало:
- Установить
npm install -g web-component-tester
Написать тест, просто html файл (по-умолчанию, в папке `./test`):<!doctype html> <html> <head> <meta charset="utf-8"> <script src="path/webcomponentsjs/webcomponents.min.js"></script> <script src="path/web-component-tester/browser.js"></script> <link rel="import" href="path/awesome-element.html"> </head> <body> <awesome-element id="fixture"></awesome-element> <script> suite('<awesome-element>', function() { test('is awesomest', function() { assert.isTrue(document.getElementById('fixture').awesomest); }); }); </script> </body> </html>
Запустить тесты:
wct
Polymer — сахар веб-компонента, поэтому и поддержка браузерами точно такая же. Таблицы были представлены выше.К слову, у меня так и не получилось запустить на старом Android-телефоне.
Polymer — оптимизация vulcanize
HTML imports позволяет быстро и удобно подключить документ в другой документ, но в этом удобстве скрывается и проблема производительности: создается множество http-запросов. Решение есть —- соединить все подключаемые файлы в один. Для этого служит утилита vulcanize.Установка:
npm install -g vulcanize
Использование:vulcanize index.html > build.html
Для удобства быстрого создания проектов есть утилита Polymer Starter Kit. После установки сразу доступно множество полезной функциональности.
Собрано в коробку:- Polymer-, Paper-, Iron- и Neon-элементы.
- Material Design-верстка.
- Роутинг с Page.js.
- Юнит тесты с помощью Web Component Tester.
- Поддержка оффлайн-работы с помощью Platinum Service Worker.
- Создание билда (включая Vulcanize).
- ES2015-поддержка.
Polymer — лишь надстройка над Web Components. Есть и другие подобные продукты:
Polymer — ссылки
Polymer — про взаимодействие с библиотеками- Angular 2
- Веб-компоненты будут внедрены в Angular 2: angularjs.blogspot.ru (eng).
- React
Официальный представитель от React Sebastian Markbage говорит, что они не будут использовать Web Components совместно с React, т. к. они идеологически разные (декларативный React против императивных Web Components): docs.google.com (eng). Однако, React и Web Components совместимы, в некоторых случаях есть польза: youtube.com (eng). - Backbone
Удобно скрестить с уже готовыми компонентами (Polymer, X-Tags, Bosonic). Используются точно так же, как обычные HTML-элементы. webcomponents.org (eng).
Рассмотрим простой пример веб-компонента и его Polymer-реализацию:Пример чистого веб-компонента:
<template> <span id="multiplier"></span> * <span id="multiplicand"></span> = <span id="result"></span> </template> <script> (function(window, document) { var ownerDocument = (document._currentScript || document.currentScript).ownerDocument; var template = ownerDocument.querySelector('template').content; var elementPrototype = Object.create(HTMLElement.prototype); var multiplier = 0, multiplicand = 0, result = 0; elementPrototype.createdCallback = function() { var shadowRoot = this.createShadowRoot(); var clone = document.importNode(template, true); shadowRoot.appendChild(clone); this.multiplier = shadowRoot.querySelector('#multiplier'); this.multiplicand = shadowRoot.querySelector('#multiplicand'); this.result = shadowRoot.querySelector('#result'); this.calculate(); }; elementPrototype.attributeChangedCallback = function(attr, oldVal, newVal) { this.calculate(); }; elementPrototype.calculate = function(){ multiplier = parseFloat( this.getAttribute('multiplier') ); multiplicand = parseFloat( this.getAttribute('multiplicand') ); this.multiplier.textContent = multiplier; this.multiplicand.textContent = multiplicand; this.result.textContent = multiplicand*multiplier; }; window.MyElement = document.registerElement('element-multiplier', {prototype: elementPrototype }); })(window, document); </script>
Подключаем в
<head>
-><link rel="import" href="element-multiplier.html">
Используем на странице (в<body>
) -><element-multiplier multiplier="3" multiplicand="2"></element-multiplier>
С Polymer будет выглядеть заметно понятней и проще:
<link rel="import" href="polymer.html"> <dom-module id="element-multiplier"> <template> <span>{{multiplier}}</span> * <span>{{multiplicand}}</span> = <span>{{result}}</span> </template> </dom-module> <script> Polymer({ is: "element-multiplier", properties: { "multiplier" : { type: Number, value: 0, observer: 'calculate' }, "multiplicand" : { type: Number, value: 0, observer: 'calculate' }, "result" : { type: Number, value: 0 } }, ready: this.calculate, calculate: function(){ this.result = this.multiplier*this.multiplicand; } }); </script>
Подключаем в
<head>
-><link rel="import" href="path/element-multiplier.html"><script src="path/webcomponents.min.js"></script>
Используем на странице (в<body>
) -><element-multiplier multiplier="3" multiplicand="2"></element-multiplier>
Примеры:
- pubnub.com — (eng) создание приложения на Polymer.
- translate.google.com — создан на Polymer.
- todomvc.com — (eng) пример TODO MVC на Polymer.
- pubnub.github.io — (eng) анонимный чат на Polymer.
- github.com — (eng) мое маленькое приложение. Идея проста: когда группа людей делает совместную покупку с одинаковыми вкладами, часто возникает путаница в расчетах долгов, когда скидываются не все сразу. Писал специально, чтобы попробовать Polymer. Там настроены тесты и vulcanize, реализована минификация JS в один файл.
Успехов! Если есть ошибки/замечания/дополнения — пишите.