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

Haunted — это легковесная библиотека для создания веб-компонентов на базе хуков, вдохновленных React. Версионирование в контексте Haunted имеет особое значение, так как состояние и ререндеринг компонентов тесно связаны с их определением. Неправильное управление версиями может привести к непредсказуемому поведению при обновлении компонентов или изменении их структуры.

Контроль версий компонентов

Каждый компонент Haunted определяется как функция, возвращающая шаблон html. С точки зрения библиотеки, идентичность функции является критическим фактором: Haunted отслеживает состояние по функции компонента. При изменении кода компонента без изменения его идентификатора состояние, связанное с предыдущей версией, может некорректно применяться к новой реализации.

import { html, component } from 'haunted';

function Counter({ initial = 0 }) {
  const [count, setCount] = useState(initial);
  return html`
    <button @click=${() => setCount(count + 1)}>
      ${count}
    </button>
  `;
}

customElements.define('x-counter', component(Counter));

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

Поддержка состояния между версиями

Haunted использует механизм WeakMap для связывания состояния с экземплярами компонентов. Это означает, что при замене функции компонента на новую версию старое состояние может быть потеряно или применено некорректно, если не учитывать версионирование. Решением является явное управление ключами состояния через свойства или уникальные идентификаторы:

function VersionedCounter({ version = 1, initial = 0 }) {
  const [count, setCount] = useState(initial, `counter-${version}`);
  return html`
    <button @click=${() => setCount(count + 1)}>
      ${count}
    </button>
  `;
}

customElements.define('x-versioned-counter', component(VersionedCounter));

Использование уникального ключа позволяет Haunted корректно различать состояния разных версий одного и того же компонента.

Совместимость API между версиями

Haunted активно развивается, но при этом старается сохранять обратную совместимость. Основные моменты:

  • Хуки useState, useEffect, useReducer остаются стабильными, поэтому обновление версий библиотеки обычно не ломает существующие компоненты.
  • Новые версии компонентов могут добавлять дополнительные свойства или события. Чтобы избежать конфликтов, рекомендуется версионировать теги компонентов или использовать префиксы в названиях:
customElements.define('x-counter-v2', component(CounterV2));
  • Изменение внутренней структуры компонента требует особого внимания к сохранению состояния и идентичности функций.

Стратегии управления версиями

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

  2. Ключи состояния и props Если тег сохраняется, необходимо различать версии через ключи состояния или новые свойства. Это гарантирует, что состояние старых экземпляров не будет случайно применено к новым версиям.

  3. Модульная структура Разделение компонентов на отдельные модули и использование сборщика позволяет импортировать конкретные версии компонентов без риска смешивания старого и нового кода.

Практика обновления компонентов

Обновление компонентов Haunted должно учитывать три аспекта: состояние, поведение и API. Пример обновления счетчика:

// Старый компонент
function Counter({ initial = 0 }) {
  const [count, setCount] = useState(initial);
  return html`<button @click=${() => setCount(count + 1)}>${count}</button>`;
}

// Новая версия с дополнительной кнопкой сброса
function CounterV2({ initial = 0 }) {
  const [count, setCount] = useState(initial, 'v2');
  return html`
    <button @click=${() => setCount(count + 1)}>${count}</button>
    <button @click=${() => setCount(initial)}>Сброс</button>
  `;
}

customElements.define('x-counter-v2', component(CounterV2));

Использование версии в ключе состояния ('v2') гарантирует, что старые экземпляры не потеряют данные, а новые получат независимое состояние.

Рекомендации по версионированию в Haunted

  • Всегда использовать уникальные имена тегов при кардинальных изменениях функционала.
  • Контролировать ключи состояния при незначительных изменениях, чтобы сохранить совместимость с предыдущими версиями.
  • Соблюдать семантику API, чтобы новые версии компонентов оставались предсказуемыми для потребителей.
  • Использовать модульную структуру и пакетные менеджеры для точного контроля версии библиотек и компонентов.

Версионирование в Haunted — это не только управление номерами версий, но и корректное разделение состояния, функций и DOM-экземпляров для безопасного обновления веб-компонентов.