PurpleSchool — курсы программирования онлайн
  • Пути
    • Frontend React разработчик
    • Frontend Vue разработчик
    • Backend разработчик Node.js
    • Fullstack разработчик React / Node.js
    • Mobile разработчик React Native
    • Backend разработчик Golang
    • Devops инженер
    • Backend разработчик Python
  • AI для кодаНовое
  • О нас
    • Отзывы
    • Реферальная программа
    • О компании
    • Контакты
  • Иконка открытия меню
    • Сообщество
    • PurpleПлюс
    • AI Собеседование
    • AI тренажёр
    • Проекты
PurpleSchool — платформа бесплатных roadmap и курсов для разработчиков
ютуб иконка
Telegram иконка
VK иконка
VK иконка
Курсы
ГлавнаяКаталог курсовFrontendBackendFullstack
Практика
КарьераПроектыPurpleПлюс
Материалы
БлогБаза знаний
Документы
Договор офертаПолитика конфиденциальностиПроверка сертификатаМиграция курсовРеферальная программа
Реквизиты
ИП Ларичев Антон АндреевичИНН 773373765379contact@purpleschool.ru

PurpleSchool © 2020 -2026 Все права защищены

  • Курсы
    • FrontendИконка стрелки
    • AI разработкаИконка стрелки
    • BackendИконка стрелки
    • DevOpsИконка стрелки
    • MobileИконка стрелки
    • ТестированиеИконка стрелки
    • Soft-skillsИконка стрелки
    • ДизайнИконка стрелки
    Иконка слояПерейти в каталог курсов
  • Бесплатно
    • Курсы
    • JavaScript Основы разработкиPython Основы PythonCSS CSS FlexboxКарта развитияВопросы для собеседований
    • База знанийИконка стрелки
    • Новостные рассылкиИконка стрелки
  • PurpleSchool — курсы программирования онлайн
    • AI для кодаНовое
    • Сообщество
    • PurpleПлюс
    • AI Собеседование
    • AI тренажёр
    • Проекты
    Главная
    Сообщество
    Микрофронтенды и Module Federation: подходы и реализация

    Микрофронтенды и Module Federation: подходы и реализация

    Аватар автора Микрофронтенды и Module Federation: подходы и реализация

    Антон Ларичев

    Иконка календаря06 июля 2026
    микрофронтендыmodule-federationwebpackархитектураreactseniorИконка уровня senior
    Картинка поста Микрофронтенды и Module Federation: подходы и реализация

    Введение

    Монолитный фронтенд — узкое место крупных команд. Когда над одним SPA работают десятки разработчиков, слияния становятся болью, деплои затяжными, а любое изменение рискует сломать всё приложение. Микрофронтенды решают эту проблему, разбивая UI на независимые части, каждую из которых можно разрабатывать, тестировать и деплоить отдельно.

    В Webpack 5 появился Module Federation — нативный механизм для загрузки кода из других сборок прямо в рантайме. Это сделало микрофронтенды доступными без сложной инфраструктуры и сторонних фреймворков.

    Архитектурные подходы

    Перед тем как переходить к коду, важно понять, какие стратегии существуют.

    Iframe-подход

    Самый простой способ: каждый микрофронтенд живёт в <iframe>. Полная изоляция по стилям и JavaScript, но слабая коммуникация между частями и плохой UX из-за отдельных скроллов и истории браузера.

    Независимые SPA на разных маршрутах

    Каждое приложение отвечает за свой URL-префикс. Shell-приложение (оркестратор) подгружает нужный SPA при переходе по маршруту. Подход хорош для крупных доменов с минимальным пересечением UI.

    Компонентная интеграция через Module Federation

    Наиболее гибкий подход: приложения делятся компонентами в рантайме. Shell монтирует компоненты из удалённых сборок как обычные React-компоненты. Именно этот способ разберём подробно.

    Module Federation: как это работает

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

    В схеме два типа участников:

    • Host (оболочка) — основное приложение, которое потребляет удалённые модули
    • Remote (поставщик) — приложение, которое экспортирует свои модули

    Настройка Remote-приложения

    // webpack.config.js удалённого приложения (каталог товаров)
    const { ModuleFederationPlugin } = require('webpack').container;
    
    module.exports = {
      plugins: [
        new ModuleFederationPlugin({
          // уникальное имя контейнера
          name: 'catalog',
          // файл точки входа федерации
          filename: 'remoteEntry.js',
          exposes: {
            // псевдоним для импорта → реальный путь к файлу
            './ProductList': './src/components/ProductList',
            './CartButton': './src/components/CartButton',
          },
          shared: {
            react: { singleton: true, requiredVersion: '^18.0.0' },
            'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
          },
        }),
      ],
    };
    

    Параметр shared критически важен: он гарантирует, что все приложения используют одну копию React, а не тянут каждое свою.

    Настройка Host-приложения

    // webpack.config.js хост-приложения (shell)
    const { ModuleFederationPlugin } = require('webpack').container;
    
    module.exports = {
      plugins: [
        new ModuleFederationPlugin({
          name: 'shell',
          remotes: {
            // псевдоним → имя контейнера@URL до remoteEntry.js
            catalog: 'catalog@http://localhost:3001/remoteEntry.js',
            checkout: 'checkout@http://localhost:3002/remoteEntry.js',
          },
          shared: {
            react: { singleton: true, requiredVersion: '^18.0.0' },
            'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
          },
        }),
      ],
    };
    

    Динамическая загрузка компонентов в React

    Удалённые модули загружаются асинхронно, поэтому используем React.lazy и Suspense:

    // src/App.jsx в host-приложении
    import React, { Suspense } from 'react';
    
    // ленивая загрузка компонента из удалённого приложения
    const ProductList = React.lazy(() => import('catalog/ProductList'));
    const CartButton  = React.lazy(() => import('catalog/CartButton'));
    
    function App() {
      return (
        <div className="shell">
          <header>
            <Suspense fallback={<span>Загрузка корзины...</span>}>
              <CartButton />
            </Suspense>
          </header>
          <main>
            <Suspense fallback={<span>Загрузка каталога...</span>}>
              <ProductList />
            </Suspense>
          </main>
        </div>
      );
    }
    

    Коммуникация между микрофронтендами

    Компоненты из разных сборок не могут напрямую пользоваться одним React Context. Для обмена данными подходят три паттерна.

    Пропсы через Host

    Самый простой способ — Host передаёт данные в удалённый компонент через пропсы:

    // Host знает текущего пользователя и пробрасывает это в каталог
    <ProductList userId={currentUser.id} onAddToCart={handleAddToCart} />
    

    Общая шина событий

    Для слабосвязанной коммуникации подходит простой pub/sub, вынесенный в shared-библиотеку:

    // packages/event-bus/index.js — общая для всех сборок
    const listeners = {};
    
    export const eventBus = {
      emit(event, data) {
        (listeners[event] || []).forEach(fn => fn(data));
      },
      on(event, fn) {
        listeners[event] = [...(listeners[event] || []), fn];
        // возвращаем функцию для отписки
        return () => {
          listeners[event] = listeners[event].filter(l => l !== fn);
        };
      },
    };
    

    URL как источник истины

    Состояние, зашитое в URL (query-параметры, pathname), автоматически доступно всем микрофронтендам без дополнительной инфраструктуры.

    Частые ошибки

    Дублирование зависимостей

    Если не указать shared или указать конфликтующие версии, каждое приложение загрузит свою копию React. Это приводит к ошибке «Invalid hook call» и росту бандла. Всегда явно декларируйте shared-зависимости с singleton: true.

    Синхронный импорт на верхнем уровне

    Module Federation загружает удалённые модули асинхронно. Статический import в точке входа без асинхронной обёртки ломает сборку. Правильное решение:

    // index.js — точка входа должна быть асинхронной
    // bootstrap.jsx содержит ReactDOM.createRoot и рендер приложения
    import('./bootstrap');
    

    Хардкод URL удалённых сборок

    http://localhost:3001 подходит только локально. В продакшене URL задаётся через переменные окружения или динамическую конфигурацию, иначе придётся пересобирать Shell при каждом изменении адреса Remote.

    Отсутствие Error Boundary

    Если удалённый сервис упал, весь Shell сломается вместе с ним. Оборачивайте каждый Remote в Error Boundary:

    // возвращает заглушку, если удалённый компонент не загрузился
    class RemoteBoundary extends React.Component {
      state = { error: null };
    
      static getDerivedStateFromError(error) {
        return { error };
      }
    
      render() {
        if (this.state.error) {
          return <div>Раздел временно недоступен</div>;
        }
        return this.props.children;
      }
    }
    

    Заключение

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

    Ключевые принципы успешной реализации: явные shared-зависимости с singleton: true, асинхронные точки входа, Error Boundary вокруг каждого Remote и конфигурация URL через переменные окружения. Начните с одного Remote на маршрут — это наименее рискованный старт — и переходите к компонентной интеграции по мере роста команды.

    Иконка глаза2

    Комментарии

    0

    Постройте личный план изучения Основы разработки до уровня Middle — бесплатно!

    Основы разработки — часть карты развития Frontend, Backend, Mobile

    • step100+ шагов развития
    • lessons30 бесплатных лекций
    • lessons300 бонусных рублей на счет

    Бесплатные лекции

    Лучшие курсы по теме

    изображение курса

    Основы Git

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.9
    3 999 ₽ 6 990 ₽
    Подробнее
    изображение курса

    HTML и CSS

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Практика в студииПрактика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.9
    3 999 ₽ 6 990 ₽
    Подробнее
    изображение курса

    CSS Flexbox

    Антон Ларичев
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.9
    бесплатно
    Подробнее

    Похожие статьи

    Картинка поста Clean Architecture: чистая архитектура для веб-разработки
    Иконка аватараАнтон
    Иконка календаря02 июля 2026
    архитектураclean architecturetypescript+ 3middleИконка уровня middle

    Clean Architecture: чистая архитектура для веб-разработки

    Clean Architecture разделяет код на независимые слои: бизнес-логика не зависит от фреймворков, БД и внешних сервисов. Разбираем на примерах TypeScript.

    Иконка чипа0
    Иконка глаза128
    Иконка комментариев0
    Картинка поста SOLID принципы в JavaScript: разбор на примерах
    Иконка аватараАнтон
    Иконка календаря26 июня 2026
    JavaScriptSOLIDООП+ 3middleИконка уровня middle

    SOLID принципы в JavaScript: разбор на примерах

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

    Иконка чипа0
    Иконка глаза116
    Иконка комментариев0
    Картинка поста Индексы в PostgreSQL: типы, применение и подводные камни
    Иконка аватараАнтон
    Иконка календаря05 июля 2026
    PostgreSQLбазы данныхиндексы+ 3middleИконка уровня middle

    Индексы в PostgreSQL: типы, применение и подводные камни

    Разбираем все типы индексов PostgreSQL: B-Tree, Hash, GIN, GiST, BRIN. Когда и какой индекс выбрать, чтобы ускорить запросы и не замедлить запись.

    Иконка чипа0
    Иконка глаза35
    Иконка комментариев0
    Иконка чипа0