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 корректно различать состояния разных версий одного и того же компонента.
Haunted активно развивается, но при этом старается сохранять обратную совместимость. Основные моменты:
useState, useEffect,
useReducer остаются стабильными, поэтому обновление версий
библиотеки обычно не ломает существующие компоненты.customElements.define('x-counter-v2', component(CounterV2));
Версионирование тегов компонентов Наиболее надежный способ предотвращения конфликтов — это изменение имени тега при обновлении компонента. Старые версии продолжают работать с существующими экземплярами DOM, а новые версии подключаются отдельно.
Ключи состояния и props Если тег сохраняется, необходимо различать версии через ключи состояния или новые свойства. Это гарантирует, что состояние старых экземпляров не будет случайно применено к новым версиям.
Модульная структура Разделение компонентов на отдельные модули и использование сборщика позволяет импортировать конкретные версии компонентов без риска смешивания старого и нового кода.
Обновление компонентов 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 — это не только управление номерами версий, но и корректное разделение состояния, функций и DOM-экземпляров для безопасного обновления веб-компонентов.