Pull to refresh
69.32
Rating
DataArt
Технологический консалтинг и разработка ПО

Понятно и просто про веб-компоненты и Polymer

DataArt corporate blog Website development *CSS *JavaScript *HTML *
Tutorial


Кто я

Я — Александр Кашеверов. По образованию — магистр радиофизики. По профессии — веб-разработчик, работаю в компании DataArt с 2011 года, с 2009 увлекаюсь IT и веб-технологиями.

О чем статья, коротко

Рассмотрим, что такое веб-компоненты и polymer. Немного поразмышляем на тему развития веба. Посмотрим на технические детали, примеры, поддержку браузерами, тестирование. Коротко, понятно, по делу. С картинками.

Вступление

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

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

Для уменьшения головной боли хорошо бы, если в контексте веб:

  • CSS не пересекался.
  • Области видимости JS не пересекались.
  • HTML был понятным и читаемым, никаких лишних элементов.


В настоящее время это не совсем так. Относительно JavaScript: приходится следить, чтобы он не работал с global scope и разные компоненты случайно не взаимодействовали друг с другом. В CSS нет и не было инкапсуляции, приходится придумывать методологии вроде MCSS и bem, чтобы ничего лишний раз не сломалось. И наконец, в HTML можно увидеть множество лишних элементов на странице, например, даже сейчас в почте gmail…



Запутанно… Не правда ли?
Фреймворки в той или иной степени внедряют компонентизацию и стараются решить эти задачи. Однако, они так же построены на всё тех же HTML, CSS, JavaScript.

Веб-компоненты — коротко

Веб медленно, но верно движется к компонентизации — это естественный процесс. Сложное можно упростить, разбив на части. Параллельно развитию фреймворков идет работа и на более низком уровне. Набирают популярность веб-компоненты. Это реализация идеи компонентизации на уровне браузера.

История веб-компонентов началась в 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>
</code> или <code>
<audio>
.

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

Наверняка многие подключали в проект Bootstrap — для этого нужно отдельно прописать подгрузку стилей и скриптов. С компонентами это можно было бы сделать проще.
<link rel="import" href="bootstrap.html">


Веб-компоненты — не фреймворк. Это набор технологий, реализованных на уровне браузера.

Веб-компоненты — поддержка браузерами & polyfills

На данный момент (ноябрь 2015) три из четырех технологий находятся в стадии «Working Draft» на W3C.
Так выглядит ситуация на данный момент (ноябрь 2015):



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

С их помощью, поддержка браузерами уже получше.



На веб-странице полифиллы подключается стандартно в head (до всех скриптов, которые используют веб-компоненты):
<script src="path/webcomponents.js"></script>


Веб-компоненты — ссылки



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>, ...

Коллекция веб-компонентов, использующих различные 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 — не фреймворк, как и веб-компоненты — не фреймворк. Polymer — это обертка и сахар. Я бы идейно ее сравнил с jQuery. jQuery создана для работы с DOM, а Polymer — для работы с веб-компонентами.

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 — поддержка браузерами

    Polymer — сахар веб-компонента, поэтому и поддержка браузерами точно такая же. Таблицы были представлены выше.

    К слову, у меня так и не получилось запустить на старом Android-телефоне.

    Polymer — оптимизация vulcanize

    HTML imports позволяет быстро и удобно подключить документ в другой документ, но в этом удобстве скрывается и проблема производительности: создается множество http-запросов. Решение есть —- соединить все подключаемые файлы в один. Для этого служит утилита vulcanize.

    Установка:
    npm install -g vulcanize
    

    Использование:
    vulcanize index.html > build.html
    


    Polymer — starter kit

    Для удобства быстрого создания проектов есть утилита Polymer Starter Kit. После установки сразу доступно множество полезной функциональности.
    Собрано в коробку:
    • Polymer-, Paper-, Iron- и Neon-элементы.
    • Material Design-верстка.
    • Роутинг с Page.js.
    • Юнит тесты с помощью Web Component Tester.
    • Поддержка оффлайн-работы с помощью Platinum Service Worker.
    • Создание билда (включая Vulcanize).
    • ES2015-поддержка.


    Polymer — альтернативы

    Polymer — лишь надстройка над веб-компонентами. Есть и другие подобные продукты:


    Polymer — ссылки



    Polymer — про взаимодействие с библиотеками

    • Angular 2
    • Веб-компоненты будут внедрены в Angular 2: angularjs.blogspot.ru (eng).
    • React
      Официальный представитель от React Sebastian Markbage говорит, что они не будут использовать веб-компоненты совместно с React, т. к. они идеологически разные (декларативный React против императивных веб-компонентов): docs.google.com (eng). Однако, React и веб-компоненты совместимы, в некоторых случаях есть польза: youtube.com (eng).
    • Backbone
      Удобно скрестить с уже готовыми компонентами (Polymer, X-Tags, Bosonic). Используются точно так же, как обычные HTML-элементы. webcomponents.org (eng).


    Веб-компоненты и Polymer — примеры

    Рассмотрим простой пример веб-компонента и его 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>
    


    Подключаем в
     
    <link rel="import" href="element-multiplier.html">


    Используем на странице (в
    ) 
    <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>
    


    Подключаем в
     
    <link rel="import" href="path/element-multiplier.html"><script src="path/webcomponents.min.js"></script>


    Используем на странице (в
    ) 
    <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 в один файл.


    Спасибо!

    Успехов! Если есть ошибки/замечания/дополнения — пишите.
Tags:
Hubs:
Total votes 25: ↑22 and ↓3 +19
Views 47K
Comments Comments 14

Information

Founded
Website
www.dataart.com
Employees
1,001–5,000 employees
Registered