Haunted — это современная библиотека для создания веб-компонентов с
использованием реактивного подхода, вдохновленного React, но
построенного на нативных возможностях браузера. Она предоставляет
hook-ориентированную архитектуру, позволяя управлять
состоянием и жизненным циклом компонентов без необходимости в
виртуальном DOM. Основной элемент Haunted — это функциональный
веб-компонент, который создаётся с помощью функции
component.
import { component, html, useState } from 'haunted';
function Counter({ initial = 0 }) {
const [count, setCount] = useState(initial);
return html`
<div>
<p>Счётчик: ${count}</p>
<button @click=${() => setCount(count + 1)}>Увеличить</button>
</div>
`;
}
customElements.define('my-counter', component(Counter));
Ключевые моменты:
html используется для описания разметки с шаблонными
литералами.useState создаёт реактивное состояние.@click — это синтаксис Haunted для привязки событий к
DOM-элементам.Haunted предоставляет несколько hook’ов для управления жизненным циклом веб-компонентов:
useEffect — выполняет побочные эффекты
после рендера, аналогично React.useConnectedCallback — вызывается при
добавлении компонента в DOM.useDisconnectedCallback — вызывается
при удалении компонента из DOM.useUpdate — отслеживает изменения
свойств компонента.Пример использования:
import { component, html, useEffect } from 'haunted';
function Logger({ message }) {
useEffect(() => {
console.log('Компонент смонтирован с сообщением:', message);
return () => console.log('Компонент размонтирован');
}, [message]);
return html`<p>${message}</p>`;
}
customElements.define('my-logger', component(Logger));
Здесь useEffect реагирует на изменения
message и выполняет очистку при размонтировании.
Состояние в Haunted создаётся через hook’и useState,
useReducer или useRef. Свойства компонента
доступны напрямую через аргументы функции, переданные при вызове
component.
function TodoItem({ task, completed }) {
const [done, setDone] = useState(completed);
return html`
<div>
<input type="checkbox" ?checked=${done} @change=${() => setDone(!done)} />
<span>${task}</span>
</div>
`;
}
Особенности:
?checked=${done} позволяет синхронизировать состояние с
атрибутами DOM.Haunted ориентирован на современные сборщики модулей: ESM, Rollup, Webpack, Vite. Основные принципы интеграции:
import/export без необходимости в
транспиляции.useState,
html, component), минимизируя размер
бандла.Пример конфигурации для Rollup:
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import { terser } from 'rollup-plugin-terser';
export default {
input: 'src/index.js',
output: {
file: 'dist/bundle.js',
format: 'esm'
},
plugins: [
resolve(),
commonjs(),
terser()
]
};
Haunted позволяет использовать динамический импорт компонентов, что ускоряет загрузку страницы и уменьшает первоначальный размер скриптов.
document.getElementById('load').addEventListener('click', async () => {
const { default: LazyComponent } = await import('./LazyComponent.js');
customElements.define('lazy-component', LazyComponent);
});
Особенности:
Haunted предоставляет возможность создавать собственные хуки, что упрощает повторное использование логики.
import { useState, useEffect } from 'haunted';
function useTimer(initial = 0) {
const [time, setTime] = useState(initial);
useEffect(() => {
const id = setInterval(() => setTime(t => t + 1), 1000);
return () => clearInterval(id);
}, []);
return time;
}
function Timer() {
const time = useTimer();
return html`<p>Прошло секунд: ${time}</p>`;
}
Преимущества:
Для проектов с Haunted важны несколько практик оптимизации:
component + хуки
отдельно).terser или аналогичные
плагины.Это позволяет уменьшить размер итогового скрипта и ускорить загрузку страниц.
Haunted сочетает минимализм нативных веб-компонентов с мощью реактивного подхода, а интеграция с современными сборщиками делает его удобным инструментом для больших приложений.