Stencil vs Svelte

Stencil и Svelte решают схожие задачи — создание современных интерфейсов — но исходят из принципиально разных архитектурных предпосылок.

Stencil — это компилятор Web Components. Его основная цель — упростить создание стандартных кастомных элементов, полностью совместимых с платформой браузера. Итогом работы Stencil всегда являются нативные Web Components, не зависящие от самого фреймворка во время выполнения.

Svelte — это компилируемый UI-фреймворк, который преобразует компоненты в оптимизированный JavaScript-код, напрямую работающий с DOM. Он не делает ставку на Web Components по умолчанию, а предлагает собственную модель компонентов.

Ключевое различие:

  • Stencil ориентирован на платформу (Web Standards)
  • Svelte ориентирован на разработчика (DX и лаконичность)

Модель компонентов

Stencil

Компоненты Stencil представляют собой классы с декораторами:

@Component({
  tag: 'my-button',
  shadow: true
})
export class MyButton {
  @Prop() label: string;

  render() {
    return <button>{this.label}</button>;
  }
}

Характерные особенности:

  • Классическая объектно-ориентированная модель
  • Декораторы (@Component, @Prop, @State, @Event)
  • JSX как язык шаблонов
  • Явная связь с Web Components API
  • Поддержка Shadow DOM как стандартной практики

Stencil-компонент всегда является кастомным HTML-элементом (<my-button>), зарегистрированным через Custom Elements.

Svelte

Компонент Svelte — это декларативный файл .svelte:

<script>
  export let label;
</script>

<button>{label}</button>

Особенности:

  • Отсутствие классов
  • Минимум абстракций
  • Реактивность встроена в синтаксис
  • Шаблон, логика и стили находятся в одном файле
  • Компонент не обязан быть Web Component

Реактивность и управление состоянием

Реактивность в Stencil

Stencil использует прокси-объекты и отслеживание изменений через декораторы:

  • @Prop() — входные свойства
  • @State() — внутреннее состояние
  • @Watch() — наблюдение за изменениями
@State() count = 0;

@Watch('count')
onCountChange(newValue: number) {
  console.log(newValue);
}

Обновление состояния приводит к перерендеру компонента. Модель близка к React, но реализована без Virtual DOM — Stencil генерирует оптимизированный код обновления.

Реактивность в Svelte

Svelte компилирует реактивность на уровне синтаксиса:

let count = 0;
$: doubled = count * 2;

Особенности:

  • Реактивные выражения ($:)
  • Автоматическое отслеживание зависимостей
  • Нет сеттеров, декораторов и хуков
  • Изменение переменной напрямую обновляет DOM

С точки зрения читаемости и плотности кода реактивность Svelte значительно компактнее.


Работа с DOM и производительность

Stencil:

  • Генерирует минимальный runtime
  • Использует прямые DOM-операции
  • Поддерживает lazy-loading компонентов
  • Оптимизирован для больших библиотек компонентов

Svelte:

  • Компилирует изменения DOM в точечные инструкции
  • Не использует Virtual DOM
  • Высокая производительность из коробки
  • Отлично подходит для интерактивных интерфейсов

На практике:

  • Stencil выигрывает в сценариях с большим количеством изолированных компонентов
  • Svelte показывает отличные результаты в цельных приложениях

Стилизация

Stencil

Stencil тесно интегрирован с Shadow DOM:

  • Инкапсуляция стилей по умолчанию
  • Поддержка :host, ::slotted
  • Возможность отключить Shadow DOM
  • Поддержка CSS Variables для темизации
:host {
  display: block;
}

Stencil хорошо подходит для design system и UI-китов, где критична изоляция стилей.

Svelte

Svelte использует scoped CSS на уровне компиляции:

  • Автоматическое добавление хешей к селекторам
  • Стили по умолчанию не протекают наружу
  • Shadow DOM не используется (опционально)
button {
  color: red;
}

Стили применяются только к текущему компоненту за счёт трансформации CSS.


Интеграция и совместимость

Stencil

Stencil-компоненты:

  • Работают в любом фреймворке (React, Angular, Vue, Svelte)
  • Могут использоваться без фреймворков
  • Поддерживают стандартные HTML-атрибуты и события
  • Отлично подходят для микрофронтендов

Stencil часто используется как инфраструктурный слой UI.

Svelte

Svelte-компоненты:

  • Лучшим образом работают внутри Svelte-приложений
  • Могут быть скомпилированы в Web Components, но это не основной сценарий
  • Менее удобны для встраивания в чужие экосистемы

Размер бандла и runtime

Stencil:

  • Runtime ~5–10 KB
  • Компоненты загружаются лениво
  • Один runtime для всей библиотеки
  • Подходит для распространения как npm-пакет

Svelte:

  • Runtime практически отсутствует
  • Код компонента полностью встраивается в бандл
  • Размер зависит от количества компонентов
  • Минимальный overhead для приложений

Типизация и экосистема TypeScript

Stencil:

  • TypeScript — основной язык
  • Автогенерация типов для компонентов
  • Генерация components.d.ts
  • Строгая типизация свойств и событий

Svelte:

  • TypeScript поддерживается, но не является фундаментом
  • Требует дополнительной конфигурации
  • Типизация менее строгая на уровне шаблонов

Типичные сценарии применения

Stencil:

  • Design systems
  • UI-библиотеки
  • Кросс-фреймворковые компоненты
  • Микрофронтенды
  • Встраиваемые виджеты

Svelte:

  • SPA и MPA
  • Интерактивные интерфейсы
  • Прототипы и стартапы
  • Приложения с акцентом на DX
  • Быстрое создание UI без лишнего boilerplate

Подход к обучению и поддержке

Stencil:

  • Более высокий порог входа
  • Требует понимания Web Components
  • Документация ориентирована на архитекторов UI
  • Меньшее сообщество, но стабильное развитие

Svelte:

  • Низкий порог входа
  • Интуитивный синтаксис
  • Активное сообщество
  • Быстрое освоение без глубоких знаний DOM API

Ключевые различия в краткой форме

  • Stencil — компилятор для Web Components

  • Svelte — UI-фреймворк с реактивным синтаксисом

  • Stencil — изоляция, стандарты, повторное использование

  • Svelte — простота, лаконичность, скорость разработки

  • Stencil — инфраструктура UI

  • Svelte — приложение целиком