Сборщики модулей

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. Основные принципы интеграции:

  1. ESM-подход: Haunted полностью поддерживает import/export без необходимости в транспиляции.
  2. Tree-shaking: благодаря модульной архитектуре можно подключать только нужные функции (useState, html, component), минимизируя размер бандла.
  3. Совместимость с TypeScript: Haunted поставляется с декларациями типов, что облегчает работу в проектах с строгой типизацией.
  4. Поддержка горячей перезагрузки: при использовании Vite или Webpack с HMR компоненты Haunted перерендериваются без полной перезагрузки страницы.

Пример конфигурации для 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);
});

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

  • Компонент подключается только при необходимости.
  • Поддерживаются стандартные сборщики: Rollup, Webpack, Vite.
  • Tree-shaking позволяет не включать ленивый компонент в основной бандл.

Расширение функционала через хуки

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.

Оптимизация сборки

Для проектов с Haunted важны несколько практик оптимизации:

  • Разделение кода на независимые модули (component + хуки отдельно).
  • Использование ленивой загрузки для редко используемых компонентов.
  • Минификация бандлов через terser или аналогичные плагины.
  • Tree-shaking всех неиспользуемых функций и утилит.

Это позволяет уменьшить размер итогового скрипта и ускорить загрузку страниц.

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