Несколько недель назад на Polymer Summit 2017 команда Ionic Framework анонсировала новый компилятор, который создает собственные веб-компоненты. Компилятор называется Stencil и сочетает в себе множество аспектов из известных библиотек и фреймворков, таких как React и Angular.

В этом посте я попытаюсь представить Stencil и то, почему я был рад взглянуть на него в первую очередь.

Сага об API веб-компонентов

Я уже несколько лет говорю об API веб-компонентов на конференциях и местных мероприятиях. Состояние API-интерфейсов постоянно меняется, и поддержка в браузерах оставляет желать лучшего (если вы не используете Chrome или Safari). Я надеюсь, что они будут стандартизированы и позволят нам создавать многоразовые нативные веб-компоненты.

Пока этого не произошло, мы полагаемся на библиотеки и фреймворки, которые позволяют нам создавать такие компоненты, как React или Angular.

Если вы его построите, они придут

Несколько недель назад команда Ionic Framework выпустила первые биты и байты Stencil. Как написано на сайте Stencil, это

Волшебный многоразовый генератор веб-компонентов

Stencil - это инструмент времени сборки, и это очень важно понимать. Результатом Stencil является 100% соответствующий стандартам Custom Element. Итак, что это значит для вас как веб-разработчика? Это означает, что вы можете использовать скомпилированный компонент из любой другой библиотеки или фреймворка. Например, если вы создали диалог в Stencil, этот диалог можно использовать в React, Angular, Polymer и т. Д. В некоторых браузерах по-прежнему потребуется использовать полифил веб-компонентов HTML5, но поддержка API в большинстве браузеров находится на стадии разработки.

Трафарет основан на таких аспектах, как:

  • Виртуальный DOM
  • Асинхронный рендеринг
  • Реактивная привязка данных
  • Машинопись
  • JSX

После нескольких проектов как в Angular, так и в React для меня было действительно естественно создать свой первый компонент в Stencil.

Создание проекта трафарета

Итак, теперь, когда мы понимаем, что такое Stencil, давайте создадим на его основе компонент. Первое, что вам нужно сделать, это создать новый проект.

Убедитесь, что на вашем компьютере установлен npm :)

Команда Ionic Framework уже создала семена для создания нового проекта, который можно найти в https: //github.com/ionic-team/stencil-starter.git.
Просто напишите в командной строке следующее:

git clone https://github.com/ionic-team/stencil-starter.git my-first-stencil-component 
cd my-first-stencil-component
git remote rm origin
npm install

и будешь готов к работе. Проект должен выглядеть так:

Создание простого компонента трафарета

Если вы новичок в TypeScript или JSX, я предлагаю сначала найти учебные пособия по этим технологиям, прежде чем двигаться дальше в этом посте.

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

Я переименовал созданный компонент my-name из исходной точки в collapsible-panel, и вот код этого компонента:

import {Component, Prop, State, Method} from '@stencil/core';

@Component({
  tag: 'collapsible-panel',
  styleUrl: 'collapsible-panel.css'
})
export class CollapsiblePanel {
  @Prop() title: string;
  @State() collapsed: boolean;

  @Method()
  toggle() {
      this.collapsed = !this.collapsed;
  }

  render() {
    return (
        <div>
            <div id="header" onClick={this.toggle.bind(this)}>
                <span>{this.title}</span>
            </div>
            <div id="content" hidden={this.collapsed}>
                <slot />
            </div>
        </div>
    );
  }
}

Давайте разберемся, что происходит.

Прежде всего, расширение файла - .tsx, что указывает на то, что код написан на TypeScript и JSX. Чтобы создать компонент Stencil, вы используете декоратор Component, который настраивает компонент с именем в DOM и стилем компонента.
Затем вы создаете класс для компонента и реализуете его. В этом классе я использую два других декоратора трафарета - декораторы Prop и State. Первый указывает свойство, которое компонент получит как атрибут компонента. Второй - внутреннее состояние компонента.

Магия компонента заключается в функции render. В функции render вы укажете компилятору Stencil, как визуализировать компонент. В функции render следует обратить внимание на несколько моментов: использование фигурных скобок для привязки (например, событие click или свойство title) и элемент slot, который используется для указания того, что контент будет предоставлен пользователем компонента (например, включение в AngularJS).

И последнее, но не менее важное: вы также можете обнаружить декоратор Method, который указывает, что функция компонента должна быть предоставлена ​​компонентом как его API.

Я добавил стиль в файл collapsible-panel.scss:

collapsible-panel {
  display: block;
  border: black dashed 1px;
}

#header {
  background: blue;
  color: white;
  cursor: pointer;
  padding: 2px;
}

и обновили файл index.html следующим элементом:

<collapsible-panel title="Collapse me!">
  <ul>
    <li>Components are awesome!</li>
    <li>They drive the web</li>
  </ul>
</collapsible-panel>

Последнее, что мне нужно было сделать, это зарегистрировать компонент в файле stencil.config.js:

exports.config = {
  bundles: [
    { components: ['collapsible-panel'] }
  ],
  collections: [
    { name: '@stencil/router' }
  ]
};

exports.devServer = {
  root: 'www',
  watchGlob: '**/**'
}

При запуске приложения с помощью команды npm start была создана следующая веб-страница со сворачиваемым компонентом:

Скомпилированный компонент

Если вы спросите себя, как выглядит компонент складной панели после компиляции Stencil, вот скомпилированный код:

/*! Built with http://stenciljs.com */
App.loadComponents(

/**** module id (dev mode) ****/
"collapsible-panel",

/**** component modules ****/
function importComponent(exports, h, t, Context, publicPath) {
var CollapsiblePanel = /** @class */ (function () {
    function CollapsiblePanel() {
    }
    CollapsiblePanel.prototype.toggle = function () {
        this.collapsed = !this.collapsed;
    };
    CollapsiblePanel.prototype.render = function () {
        return (h("div", 0,
            h("div", { "o": { "click": this.toggle.bind(this) }, "a": { "id": "header" } },
                h("span", 0, this.title)),
            h("div", { "a": { "id": "content", "hidden": this.collapsed } },
                h(0, 0))));
    };
    return CollapsiblePanel;
}());

exports['COLLAPSIBLE-PANEL'] = CollapsiblePanel;
},


/***************** collapsible-panel *****************/
[
/** collapsible-panel: tag **/
"COLLAPSIBLE-PANEL",

/** collapsible-panel: members **/
[
  [ "collapsed", /** state **/ 5 ],
  [ "title", /** prop **/ 1 ]
],

/** collapsible-panel: host **/
{},

/** collapsible-panel: events **/
0 /* no events */,

/** collapsible-panel: propWillChanges **/
0 /* no prop will change methods */,

/** collapsible-panel: propDidChanges **/
0 /* no prop did change methods */,

/** collapsible-panel: shadow **/
1 /* use shadow dom */

]
)

Функция h в скомпилированной функции render основана на Preact и предназначена для преобразования написанного вами JSX-кода в обычный JavaScript.

Резюме

Трафарет выглядит очень многообещающе. Он позволяет создавать стандартные веб-компоненты, которые могут использоваться любой библиотекой и фреймворком. Компонент, который я создал, очень прост, и я не затронул многие аспекты Stencil. В следующих статьях я расскажу о других аспектах компилятора, так что есть чего ожидать ☺

Кстати, мне очень нравится идея собственных веб-компонентов, и я надеюсь, что они скоро будут адаптированы всеми браузерами.