Концепция микрофронтендов и место Module Federation

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

Ключевая идея заключается в разделении фронтенда по бизнес-доменам, а не по техническим слоям. Если традиционный подход группирует код по типам (components, services, utils), то микрофронтенды группируют функциональность по продуктовым областям: корзина, каталог, профиль пользователя, платежи. Это позволяет разным командам работать параллельно без жёсткой синхронизации релизов.


Микрофронтенды можно рассматривать как развитие идей микросервисов, перенесённых в браузер. Основные характеристики:

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

Независимое развертывание Изменения в одном микрофронтенде не требуют пересборки всего приложения.

Композиция в рантайме Финальное приложение формируется не на этапе сборки, а во время выполнения в браузере или на сервере.

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


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

Основная сложность микрофронтендов — объединение независимых бандлов в единое приложение без конфликта зависимостей и дублирования кода. До появления специализированных механизмов использовались:

  • iframe-интеграция
  • runtime-загрузка UMD-модулей
  • systemjs
  • ручная оркестрация зависимостей

Эти подходы либо создавали изоляцию ценой сложности взаимодействия, либо приводили к конфликтам зависимостей и проблемам версионирования.

Именно здесь сборщик Webpack стал платформой для внедрения концепции Module Federation.


Module Federation как механизм композиции

Module Federation — это архитектурный механизм Webpack 5, позволяющий одному JavaScript-приложению динамически использовать модули, собранные и опубликованные другим независимым приложением.

Суть заключается в том, что сборка не является конечной точкой интеграции. Вместо этого каждый билд может:

  • экспортировать модули наружу (remote)
  • импортировать модули из других сборок (host)
  • одновременно быть и host, и remote

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


Базовая модель: host и remote

В архитектуре Module Federation выделяются два основных типа приложений:

Host Приложение-оркестратор, которое собирает интерфейс из внешних микрофронтендов.

Remote Приложение-провайдер, которое экспортирует свои модули для использования другими.

Эта модель не является строгой: одно приложение может одновременно быть host и remote.


Конфигурация Module Federation

Ключевая часть реализации — плагин ModuleFederationPlugin.

Пример конфигурации remote-приложения:

const { ModuleFederationPlugin } = require("webpack").container;

module.exports = {
  output: {
    publicPath: "auto",
  },
  plugins: [
    new ModuleFederationPlugin({
      name: "catalog",
      filename: "remoteEntry.js",
      exposes: {
        "./ProductList": "./src/ProductList",
        "./ProductCard": "./src/ProductCard",
      },
      shared: {
        react: { singleton: true, strictVersion: true },
        "react-dom": { singleton: true, strictVersion: true },
      },
    }),
  ],
};

Здесь:

  • name — уникальное имя контейнера
  • filename — точка входа для удалённой загрузки
  • exposes — публичные модули, доступные другим приложениям
  • shared — общие зависимости

Host-конфигурация:

const { ModuleFederationPlugin } = require("webpack").container;

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: "shell",
      remotes: {
        catalog: "catalog@http://localhost:3001/remoteEntry.js",
      },
      shared: {
        react: { singleton: true },
        "react-dom": { singleton: true },
      },
    }),
  ],
};

Использование удалённого модуля:

import ProductList from "catalog/ProductList";

export default function Page() {
  return <ProductList />;
}

Раннертайм-архитектура Module Federation

В отличие от классического бандлинга, Module Federation работает в два этапа:

Этап сборки Webpack формирует контейнер, регистрирует exposed-модули и создаёт манифест remoteEntry.js.

Этап выполнения Host приложение:

  • загружает remoteEntry.js
  • инициализирует контейнер
  • разрешает зависимости
  • динамически импортирует нужные модули

Это означает, что интеграция происходит в браузере, а не в CI/CD пайплайне.


Разделение зависимостей и механизм shared scope

Одна из ключевых проблем микрофронтендов — дублирование библиотек. Если каждый remote включает свою копию React, приложение может получить несколько независимых экземпляров, что ломает контекст, хуки и состояние.

Для решения используется shared scope.

Webpack позволяет объявить зависимости как shared:

  • singleton — только одна версия в рантайме
  • strictVersion — жёсткая проверка версии
  • requiredVersion — минимально допустимая версия

Пример:

shared: {
  react: {
    singleton: true,
    requiredVersion: "^18.0.0",
  },
}

Это превращает зависимости в централизованно управляемые ресурсы.


Версионирование и проблема совместимости

В микрофронтендах возникает конфликт между независимостью команд и необходимостью совместимости.

Основные стратегии:

Жёсткое выравнивание версий Все микрофронтенды используют одинаковые версии библиотек.

Peer dependencies на уровне shared Зависимости объявляются как внешние контракты.

Изоляция через разные версии Допустимо при отсутствии shared singleton, но увеличивает размер бандла.

Module Federation позволяет гибко комбинировать эти стратегии, но требует дисциплины в управлении зависимостями.


Динамическая загрузка и code splitting на уровне приложений

Module Federation расширяет классический code splitting. Если обычный split делит код внутри одного приложения, то federation делит систему на независимые бандлы.

Это приводит к появлению нового уровня ленивой загрузки:

  • загрузка удалённого приложения по маршруту
  • подгрузка компонентов по требованию
  • кэширование remoteEntry

Пример динамического подключения:

const RemoteButton = React.lazy(() =>
  import("uiLibrary/Button")
);

Паттерны использования Module Federation

Shell + micro apps Центральное приложение управляет маршрутизацией и подгружает микрофронтенды по страницам.

Feature federation Каждый бизнес-функционал — отдельный remote (например, checkout, search, profile).

Widget federation Мелкие независимые компоненты (баннеры, рекомендации, виджеты аналитики).

Vertical slicing Разделение по продуктовым доменам с минимальной связностью между модулями.


Проблемы и ограничения архитектуры

Несмотря на гибкость, микрофронтенды с Module Federation вводят ряд сложностей:

Рост сложности инфраструктуры Появляется необходимость управлять множеством сборок и точек деплоя.

Версионные конфликты Несогласованные зависимости могут приводить к runtime-ошибкам.

Сложность отладки Ошибки проявляются только в интегрированном окружении.

Задержки загрузки Удалённые модули увеличивают количество HTTP-запросов и время первого рендера.

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


Влияние Module Federation на архитектуру фронтенда

Module Federation изменяет саму модель мышления о фронтенде. Приложение перестаёт быть единым артефактом сборки и превращается в композицию независимых поставщиков функциональности.

Webpack в этой модели перестаёт быть просто bundler-ом и становится runtime-инфраструктурой для оркестрации модулей. Это смещает границу между сборкой и выполнением, делая фронтенд более похожим на распределённую систему.

Появляется новая ответственность:

  • управление контрактами модулей
  • контроль совместимости зависимостей
  • проектирование границ доменов
  • баланс между независимостью и целостностью UI

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