Коммуникация между микроприложениями

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


Использование глобального состояния

Для связи микроприложений можно применять глобальное состояние, управляемое библиотеками вроде Redux, Zustand или встроенными средствами Preact (useContext). Такой подход позволяет хранить единое состояние, которое доступно любому компоненту, подключенному к хранилищу.

Пример с Preact Context:

import { h } from 'preact';
import { createContext } from 'preact';
import { useContext, useState } from 'preact/hooks';

const AppContext = createContext();

export const AppProvider = ({ children }) => {
    const [sharedData, setSharedData] = useState({ user: null });

    return (
        <AppContext.Provider value={{ sharedData, setSharedData }}>
            {children}
        </AppContext.Provider>
    );
};

export const useAppContext = () => useContext(AppContext);

Каждое микроприложение может подключаться к AppContext и получать либо обновлять состояние:

import { useAppContext } from './AppProvider';

const UserProfile = () => {
    const { sharedData, setSharedData } = useAppContext();

    return (
        <div>
            <p>Пользователь: {sharedData.user?.name || 'Гость'}</p>
            <button onCl ick={() => setSharedData({ user: { name: 'Иван' } })}>
                Войти
            </button>
        </div>
    );
};

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


Обмен событиями через кастомные события

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

Пример отправки и обработки события:

// Микроприложение A
const sendMessage = () => {
    const event = new CustomEvent('userLoggedIn', { detail: { name: 'Иван' } });
    window.dispatchEvent(event);
};

// Микроприложение B
window.addEventListener('userLoggedIn', (e) => {
    console.log('Пользователь вошёл:', e.detail.name);
});

Преимущества:

  • Не требуется прямой импорт компонентов.
  • Легко масштабируется при добавлении новых микроприложений.
  • Обеспечивает асинхронную реакцию на события.

Недостатки:

  • Нет строгой типизации данных, что повышает риск ошибок.
  • Сложнее отслеживать поток данных при большом количестве событий.

Использование шины событий (Event Bus)

Шина событий — это паттерн, который создаёт централизованное место для обмена событиями между микроприложениями. В Preact её можно реализовать с помощью объекта EventTarget или сторонних библиотек.

Пример реализации Event Bus:

class EventBus extends EventTarget {
    emit(event, detail) {
        this.dispatchEvent(new CustomEvent(event, { detail }));
    }

    on(event, callback) {
        this.addEventListener(event, callback);
    }

    off(event, callback) {
        this.removeEventListener(event, callback);
    }
}

export const bus = new EventBus();

Использование в микроприложениях:

// Микроприложение A
import { bus } from './EventBus';
bus.emit('themeChanged', { theme: 'dark' });

// Микроприложение B
import { bus } from './EventBus';
bus.on('themeChanged', (e) => {
    console.log('Новая тема:', e.detail.theme);
});

Преимущества:

  • Централизованное управление событиями.
  • Лёгкость добавления подписчиков.
  • Удобно для динамически загружаемых микроприложений.

Передача данных через props при встроенных микроприложениях

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

const ChildApp = ({ user }) => <p>Пользователь: {user.name}</p>;

const ParentApp = () => {
    const user = { name: 'Иван' };
    return <ChildApp user={user} />;
};

Ключевой момент: props подходят для тесно связанных компонентов, но неэффективны для обмена данными между независимыми микроприложениями.


Стратегии синхронизации данных

  1. Подписка на глобальное состояние — данные автоматически обновляются при изменении состояния.
  2. Событийная шина — микроприложения реагируют на события независимо друг от друга.
  3. Прямые вызовы через props или колбэки — эффективны при тесной связи между компонентами.
  4. Комбинированный подход — глобальное состояние для критичных данных, событийная шина для менее важных и редко изменяющихся событий.

Особенности Preact при работе с микроприложениями

  • Малый размер библиотеки позволяет внедрять микроприложения без значительной нагрузки на страницу.
  • Совместимость с React API упрощает использование известных паттернов управления состоянием.
  • Hooks (useState, useEffect, useContext) обеспечивают реактивность и удобную подписку на данные между модулями.
  • Изоляция компонентов снижает вероятность конфликтов между микроприложениями, если применяются контексты и событийная шина.

Эффективная коммуникация между микроприложениями в Preact строится на комбинировании глобального состояния, событийной шины и props, с учётом степени изоляции модулей и частоты обновления данных. Такой подход обеспечивает масштабируемость, модульность и простоту поддержки больших приложений.