Версионирование компонентов

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


Компонент в Lit — это изолированный, переиспользуемый элемент, который может применяться в разных проектах, командах и даже организациях. Без чёткой стратегии версионирования любое изменение в компоненте превращается в потенциальный источник ошибок:

  • ломаются существующие шаблоны;
  • меняется поведение без явного указания;
  • усложняется обновление зависимостей;
  • невозможно гарантировать стабильность API.

Версионирование решает эти проблемы, формализуя жизненный цикл компонента.


Семантическое версионирование как основа

В экосистеме JavaScript стандартом является Semantic Versioning (SemVer):

MAJOR.MINOR.PATCH

Применительно к Lit-компонентам:

  • MAJOR — несовместимые изменения API компонента;
  • MINOR — добавление функциональности без нарушения совместимости;
  • PATCH — исправления ошибок без изменения API.

Пример:

my-button@2.1.3
  • 2 — вторая несовместимая версия API;
  • 1 — добавлены новые возможности;
  • 3 — исправлены баги.

Что считается публичным API компонента

Для корректного версионирования необходимо строго определить, что именно является контрактом компонента.

К публичному API относятся

  • имя custom element (<my-button>);
  • публичные свойства (@property);
  • публичные методы;
  • события (dispatchEvent);
  • атрибуты;
  • CSS Custom Properties;
  • CSS Parts (::part).

Любое изменение этих элементов потенциально влияет на потребителей компонента.

Не является публичным API

  • приватные поля и методы;
  • внутренняя структура шаблона;
  • вспомогательные функции;
  • внутренние классы и состояния.

Версионирование через npm-пакеты

Наиболее распространённый подход — версионирование на уровне пакета.

@company/ui-button

Версия пакета отражает состояние всех компонентов внутри него.

Пример структуры

package.json
└─ version: "1.4.0"

Обновление версии происходит при изменении любого компонента в пакете, что удобно для монорепозиториев и дизайн-систем.


Версионирование отдельных компонентов

При необходимости независимого развития компонентов используются отдельные пакеты:

@company/button
@company/modal
@company/input

Каждый компонент имеет собственный жизненный цикл и версию, что снижает связность и упрощает обновления.


Несовместимые изменения (Breaking Changes)

Изменение версии MAJOR требуется в следующих случаях:

  • переименование компонента;
  • удаление или переименование свойства;
  • изменение типа свойства;
  • изменение обязательности свойства;
  • изменение структуры событий;
  • удаление CSS part или custom property.

Пример

// Было
@property({ type: Boolean }) disabled;

// Стало
@property({ type: String }) disabled;

Такое изменение требует повышения MAJOR-версии.


Добавление функциональности (MINOR)

MINOR-версия повышается, если:

  • добавлено новое необязательное свойство;
  • добавлено новое событие;
  • добавлен CSS part;
  • расширено поведение без изменения старого.
@property({ type: Boolean }) loading = false;

Существующий код продолжает работать без изменений.


Исправления ошибок (PATCH)

PATCH-версия увеличивается, если:

  • исправлены баги;
  • улучшена производительность;
  • устранены визуальные дефекты;
  • изменена внутренняя логика без влияния на API.

Версионирование имени custom element

В редких случаях используется версионирование через имя тега:

<my-button-v1></my-button-v1>
<my-button-v2></my-button-v2>

Преимущества

  • возможность одновременного использования нескольких версий;
  • безопасная миграция.

Недостатки

  • увеличение количества компонентов;
  • усложнение поддержки;
  • рост bundle size.

Подход оправдан для крупных библиотек с долгой поддержкой старых версий.


Поддержка устаревшего API (Deprecation)

Перед breaking-изменениями рекомендуется вводить стадию устаревания.

Практика deprecation в Lit

  • пометка свойства как устаревшего в документации;
  • вывод предупреждения в консоль:
updated(changed: Map<string, unknown>) {
  if (changed.has('oldProp')) {
    console.warn('oldProp устарел и будет удалён в версии 2.0');
  }
}
  • сохранение обратной совместимости минимум на одну MINOR-или MAJOR-ветку.

Версионирование CSS API

CSS — часть контракта компонента.

Изменения, требующие MAJOR

  • удаление CSS custom property;
  • удаление ::part;
  • изменение смысловой нагрузки переменной.

Безопасные изменения

  • добавление новых CSS variables;
  • добавление новых parts;
  • улучшение дефолтных значений.

Changelog как обязательный элемент

Каждая версия должна сопровождаться changelog’ом.

Рекомендуемая структура

## 2.0.0
- BREAKING: удалено свойство `iconPosition`
- Добавлено событие `toggle`

## 1.5.0
- Добавлено свойство `loading`

## 1.4.2
- Исправлена ошибка рендеринга

Changelog — ключевой инструмент для контроля обновлений.


Версионирование и тестирование

Корректное версионирование невозможно без тестов.

  • unit-тесты фиксируют поведение API;
  • snapshot-тесты выявляют визуальные изменения;
  • regression-тесты предотвращают незапланированные breaking changes.

Любое изменение, ломающие тесты потребителей, должно считаться несовместимым.


Версионирование в монорепозиториях

В монорепозиториях применяются два подхода:

Единая версия

Все компоненты обновляются синхронно.

Плюсы:

  • простота;
  • согласованность.

Минусы:

  • лишние обновления.

Независимые версии

Каждый пакет имеет свою версию.

Плюсы:

  • гибкость;
  • точечные обновления.

Минусы:

  • сложность управления.

Автоматизация версионирования

Для Lit-проектов часто применяются:

  • conventional commits;
  • semantic-release;
  • changesets.

Они позволяют автоматически:

  • определять тип изменений;
  • обновлять версии;
  • генерировать changelog;
  • публиковать пакеты.

Совместимость и долгосрочная поддержка

Грамотное версионирование превращает Lit-компоненты в надёжный фундамент интерфейсов:

  • компоненты можно обновлять без страха;
  • изменения прозрачны;
  • API остаётся стабильным;
  • экосистема развивается предсказуемо.

Версионирование — это не формальность, а архитектурный инструмент, напрямую влияющий на качество и жизнеспособность компонентной системы.