Микрофронтенды

SkateJS — это современная библиотека для создания веб-компонентов на JavaScript, основанная на стандарте Web Components. Она предоставляет легковесный, реактивный и модульный подход, позволяющий строить интерфейсы с высокой степенью переиспользуемости. В отличие от больших фреймворков, SkateJS минимизирует абстракции, оставляя разработчику контроль над жизненным циклом компонентов и их поведением.

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


Создание компонентов

Для определения нового компонента используется функция define. Она связывает имя тега с классом компонента и его опциями:

import { define, Component, h } from 'skatejs';

class MyButton extends Component {
  static get props() {
    return {
      label: String,
      disabled: Boolean
    };
  }

  render() {
    return h('button', { disabled: this.disabled }, this.label);
  }
}

define('my-button', MyButton);

Основные элементы:

  • props — определяет свойства компонента с типами, значениями по умолчанию и реактивностью.
  • render() — описывает виртуальный DOM, используемый для обновления UI.
  • h() — функция гиперэлемента для создания элементов, аналогичная JSX, но без необходимости трансформации.

Свойства автоматически становятся реактивными: любое их изменение вызывает повторный рендер компонента.


Реактивность и жизненный цикл

SkateJS использует реактивный механизм на уровне свойств и предоставляет методы жизненного цикла, которые позволяют управлять состоянием компонента:

  • connectedCallback() — вызывается при подключении компонента к DOM.
  • disconnectedCallback() — вызывается при удалении из DOM.
  • updated() — вызывается после обновления свойств и рендера.

Пример использования:

class CounterComponent extends Component {
  static get props() {
    return { count: Number };
  }

  connectedCallback() {
    super.connectedCallback();
    console.log('Component added to DOM');
  }

  updated(prevProps) {
    console.log('Count changed from', prevProps.count, 'to', this.count);
  }

  render() {
    return h('div', {}, `Count: ${this.count}`);
  }
}

define('counter-component', CounterComponent);

Работа с микрофронтендами

SkateJS идеально подходит для микрофронтенд-архитектур, так как:

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

Пример интеграции нескольких компонентов в одну страницу:

import './header-component.js';
import './footer-component.js';
import './product-card.js';

document.body.innerHTML = `
  <header-component></header-component>
  <product-card></product-card>
  <footer-component></footer-component>
`;

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


Управление состоянием

Для управления состоянием SkateJS использует свойства компонента и события. Прямого глобального стореджа нет, но через кастомные события компоненты могут взаимодействовать друг с другом:

class ChildComponent extends Component {
  static get props() {
    return { value: Number };
  }

  increment() {
    this.value += 1;
    this.dispatchEvent(new CustomEvent('value-changed', { detail: this.value }));
  }

  render() {
    return h('button', { onclick: () => this.increment() }, `Increment ${this.value}`);
  }
}

define('child-component', ChildComponent);

class ParentComponent extends Component {
  constructor() {
    super();
    this.handleChange = this.handleChange.bind(this);
  }

  connectedCallback() {
    super.connectedCallback();
    this.addEventListener('value-changed', this.handleChange);
  }

  handleChange(event) {
    console.log('New value from child:', event.detail);
  }

  render() {
    return h('div', {}, h('child-component'));
  }
}

define('parent-component', ParentComponent);

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


Стили и Shadow DOM

SkateJS поддерживает Shadow DOM, что позволяет изолировать стили компонентов:

class StyledButton extends Component {
  render() {
    return h('button', { class: 'btn' }, 'Click me');
  }

  static get styles() {
    return `
      button.btn {
        background-color: #007bff;
        color: white;
        border: none;
        padding: 0.5em 1em;
        cursor: pointer;
      }

      button.btn:hover {
        background-color: #0056b3;
      }
    `;
  }
}

define('styled-button', StyledButton);

Стили применяются только внутри компонента, предотвращая конфликты CSS между микрофронтендами.


Интеграция с другими библиотеками

SkateJS может работать совместно с React, Vue или Angular, используя веб-компоненты как обёртки:

// В React
import 'my-button';

function App() {
  return <my-button label="Click me" />;
}

Это позволяет поэтапно мигрировать существующие приложения на микрофронтенды, не переписывая весь код с нуля.


Практические рекомендации

  • Использовать props для реактивных данных вместо прямого доступа к DOM.
  • Разделять компоненты по функциональному признаку для микрофронтендов.
  • Применять Shadow DOM для изоляции стилей и предотвращения конфликтов.
  • События и кастомные события использовать для взаимодействия между компонентами.
  • Минимизировать зависимости, оставляя компоненты максимально автономными.

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