Polymer, драка за производительность

в 18:27, , рубрики: devops, polymer, polymer.js, web-разработка, webcomponents, веб-дизайн, высокая производительность

Ни для кого не секрет, хотя не каждый в курсе, что вебкомпоненты — наше будущее. Это будущее ещё не наступило, но уже вот-вот. Один из способов приблизить это будущее — библиотека Polymer от одной малоизвестной корпорации Google. Одна из причин, по которой будущее не наступает — это совместимость с браузерами и вызванное отсутствием этой совместимости падение производительности. Иногда оно незначительное, а иногда критическое.

Библиотека Polymer, скажу с предубеждением, хорошая, код получается красивый и чистый, а вот падение производительности во всё ещё популярном браузере Firefox — то что не сделает её популярной в ближней перспективе по моему мнению. Ибо кому оно надо возится, если есть другие, более работающие вещи, а поиски в этих ваших в интернетах решения не дают.
Однако может всё же можно что сделать? Так точно. Можно!

Если вы дочитали до этого места и не утратили интереса, то скорее всего вы в курсе, что такое Polymer в текущей своей второй версии и как именно он объявляет зависимости и полифилы. Тег <link rel="import">, который для этого используется, и есть корень проблемы, он не поддерживается и никогда не будет поддерживается в Firefox.

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

Что с этим делать, спросите вы? Может есть сборочные инструменты какие? Может команда малоизвестной корпорации уже постаралась?
Сборочный инструмент есть, но в результате у нас не несколько, а один <link rel="import">, в котором ассорти html и тегов script.
Постойте, а как же билд в один js? А никак! Или всё же как-то?

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

Imports use ES6 import syntax, not <link rel="import">.
Templates are defined by providing a template getter that returns a string—not the <dom-module> and <template> elements.

Чистый JS, короче. А теперь посмотрим, как он сделан. Ведь свои компоненты мы всегда можем переписать, а что делать с вендорными iron и paper, например.
Для начала посмотрим, что с ними сделали наши друзья.
iron-icon
iron-form
Они просто автоматически сконвертировали компоненты автоматически в чисто яваскриптовые.
Перенесли шаблоны из тега в свойство объекта и обернули компоненты в функцию автоматического добавления.
Ну так любой сможет, поэтому давайте попробуем сами.

Для начала соберём файлы с компонентами в один штатным polymer build, а затем натравим на результат gulp и попробуем получить js.

let cheerio = require('gulp-cheerio');
...
    .pipe(cheerio(
      {
        run: function ($) {
          $('body > div > *').each(function () {
            if (this.tagName === 'script') {
              return;
            }
            let $this = $(this);
            if (this.tagName === 'dom-module') {
              let script = $this.children('script').html();
              let template = $this.children('template').html();
              if (template && script) {
                script = script.replace('Polymer({', "Polymer({_template:`" + template + '`,');
                script = script.replace('static get is()', 'static get template(){return `' + template + '`}static get is()');
                $this.after($('<script>' + script + '</script>'));
                $this.remove();
                return;
              }
            }
            $this.after($('<script>Polymer.addToHead(`' + $.html(this) + '`);</script>'));
            $this.remove();
          });
        }, parserOptions: {decodeEntities: false}
      }))

где код

Polymer.addToHead = (code) => {
  let a = document.createElement('div');
  a.style.display = 'none;';
  a.innerHTML = code;
  document.head.appendChild(a);
};

Должен быть подключен сразу после <link rel="import" href="../../libraries/polymer/polymer.html"/>, ну или как вы там сами себе придумаете.
В результате мы получаем html состоящий исключительно из тегов <script>, что уже намного ближе к желаемому результату.

    .pipe(splitJsCss({
      type: ['js']
    }))
    .pipe(gzip())

И вот у нас уже сжатый js на выходе, который можно подключить как любой другой js так, как это принято в вашем проекте.
Внезапно, вдруг(tm) исчезает задержка в Firefox. Нет накладных расходов на догрузку и парсинг, всё исполняется синхронно. И кешируется согласно общих политик сайта.

Не могу сказать, что всё это так же изящно, как стрелочные функции в ES6, но библиотекой Polymer стало можно пользоваться гораздо гораздее, чем буквально за час до прочтения этой статьи.

P.S. Есть ли недостатки? Ну если вы особенно хитро раньше подгружали компоненты по требованию, вам теперь придётся самостоятельно следить за двойным исполнением, если конечно оно у вас было.

P.S.S. Почему драка, потому что перед написанием собственного сборщика я пытался предложить разработчикам самим перенести шаблоны в яваскрипт, но общего языка не удалось найти. Библиотека позволяющая писать красивый код и разработчики душащие своими руками саму возможность широкого её использования уже сегодня.

Автор: Punk_UnDeaD

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js