Stencil: компилятор Web Components и PWA
Кратко об опыте использования Stencil, который позиционируется, как современное развитие UI фреймворков нацеленных на создание визуальных компонентов.
Stencil был создан командой Ionic Framework для развития одноименной библиотеки UI компонентов. Сутью инструмента является итоговая компиляция в соответствии со спецификациями Web Components. Это позволяет добиться переиспользуемости и универсальности компонентов на Stencil.
Ниже кратко опишу свой опыт использования Stencil на протяжении 5-ти месяцев. За это время я создал несколько десятков UI компонентов разного уровня сложности и написал одно SPA приложение с использование Stencil. Использовал Stencil в монорепозиториях с lerna. Сразу оговорюсь, что не пробовал использовать Stencil для PWA, Web Workers и не представляю насколько хорошо работают компоненты в мобильных браузерах.
Немного механики
Хотя Stencil и компилируется в Web Component, но помимо Custom Element и Shadow DOM из спецификации он использует собственный загрузчик (обертка над customElements.define
) и virtual DOM (VDOM). Это дает возможность использовать HMR и lazy loading при написании Stencil компонентов.
Компилируется компонент с помощью TypeScript, а сборка осуществляется посредством Rollup. Нюансы этого процесса скрыты от разработчика обертками компилятора Stencil. Для стилей могут быть использованы sass, less, postcss, stylus.
Stencil сразу содержит cli и dev server. Дополнительно можно использовать плагины Rollup. Для тестов используется Jest и в качестве движка e2e тестов - puppeteer.
На выходе Stencil соберет бандлы для разных версий браузеров (с поддержкой ES6 Module и без неё), полифилы, загрузчик и типы. Дополнительно можно автоматически сгенерировать API компонента и добавить его в README или сохранить в виде json
файла.
Особенности
Stencil можно воспринимать как комбайн для написания Web Component с собственным рендером через VDOM. Это накладывает ряд ограничений на изменение процесса создания компонента. К примеру, теряется гибкость настройки Rollup и среды для выполнения тестов. С другой стороны, мы сразу получаем готовую инфраструктуру разработки компонентов. Это существенно экономит время на старте и для несложных наборов UI компонентов.
Для чего Stencil хорошо подходит
Лучше всего Stencil подходит для создания UI компонентов низкой и средней сложности (т.е. без глобального стейта, с одним или несколькими визуальными представлениями). Собственно, так его и позиционируют разработчики Ionic. При этом неважно насколько много будет компонентов, главное, чтобы они не зависели от единого стейта.
Stencil имеет свои Lifecycle методы в дополнение к тем, что определены в стандарте Web Components. Шаблоном для компонента является JSX разметка. В компонентах активно используются декораторы. Всё это делает из Stencil хороший инструмент для создания библиотек UI компонентов.
Особенности
Благодаря VDOM Stencil дает возможность использовать ref
- прямая ссылка на ноду в DOM компонента. Но это же, в свою очередь, приводит к нетипичному поведению this
внутри класса компонента. Оно ссылается не на Custom Element, а на компонент Stencil. Получить ссылку на сам элемент можно через специальный декоратор:
import { Element } from '@stencil/core'; export class TodoList { @Element() el: HTMLElement; getListHeight(): number { return this.el.getBoundingClientRect().height; } }
Ещё один нюанс - это работа с нативными событиями, если их использовать через декоратора @Event()
, то Stencil выбросит предупреждение при компиляции. Это можно обойти, если диспатчить события самостоятельно, но тогда такое событие не будет учтено при генерации документации.
Интересным моментом является использование монорепозитория, в котором каждый компонент является независимым Stencil проектом. При создании библиотеки UI компонентов стоит учитывать, что Stencil не рассчитан на монорепозитории. К примеру, с lerna придется писать дополнительные скрипты публикации. Данный подход помимо явных плюсов независимости компонентов будет приводить к избыточности т.к. каждый компонент Stencil имеет собственный загрузчик и VDOM. На сколько это накладно и при каких объемах начнет сказываться на производительности сказать не могу. Эмпирически выявили, что при использовании до 10-ти таких компонентов в приложении проблем не возникало.
Для чего лучше выбрать другой инструмент
Если стоит задача создания полноценного SPA приложения. Это обусловлено отсутствием или слабой развитостью инструментов необходимых при разработке масштабных приложений.
Особенности
В экосистеме Stencil, на данный момент, нет удобного способа для управления маршрутизацией внутри SPA приложения и работой с глобальным состоянием. Команда Ionic предлагает для управления состоянием использовать Redux, но сам пакет stencil-redux давно не обновлялся и не соответствует последней версии Stencil. Помимо этого использование данного подхода сильно осложнено дополнительными связками, которые отсутствуют в React. Ситуация с роутером схожая. Команда разработчиков Stencil попыталась создать аналог React роутера, но сейчас решение очень "сырое" и не подходит для масштабных приложений.
Возможно, со временем ситуация изменится, но пока разработка SPA на Stencil связана с множеством сложностей.
Документация
У Stencil хорошая начальная документация, её вполне достаточно для старта и написания небольших или средних UI компонентов. По более глубоким вопросам ответ часто приходится искать в issue или на форумах.
Стоит отметить, что команда и сообщество Stencil периодически пишет статьи, которые частично раскрывают особенности работы.
Кратко
Идеальным инструмент назвать нельзя, но он решает вполне определенные задачи и может быть использован для создания библиотек UI компонентов независимых от фреймворков.
Будущее Stencil пока не ясно, сможет ли он найти свою нишу среди популярных инструментов фронтенд разработчиков.