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 на маршрут — это наименее рискованный старт — и переходите к компонентной интеграции по мере роста команды.

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

    Комментарии

    0

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

    Neovim - практика и настройка — часть карты развития Frontend, Backend, DevOps

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

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

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

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

    React и Redux Toolkit

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

    Zustand

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

    Next.js - с нуля

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

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

    Картинка поста Микросервисная архитектура для начинающих: гайд с примерами
    Иконка аватараАнтон
    Иконка календаря23 сентября 2026
    микросервисыархитектураbackend+ 2juniorИконка уровня junior

    Микросервисная архитектура для начинающих: гайд с примерами

    Микросервисная архитектура простыми словами: чем она отличается от монолита, какие есть плюсы и минусы, и как спроектировать первую систему на микросервисах — с примерами кода.

    Иконка чипа0
    Иконка глаза196
    Иконка комментариев0
    Иконка аватараАнтон
    Иконка календаря01 октября 2026
    AI-инструментыDevOpsразработка+ 2middleИконка уровня middle

    Gemini CLI в России: как установить и настроить

    Установить Gemini CLI из России можно без VPN и без ухищрений — это обычный npm-пакет, он скачивается и запускается на любой машине. Упирается всё на следующем шаге: 18 июня 2026 года Google перестал обслуживать запросы Gemini CLI для бесплатных аккаунтов и подписчиков Google AI Pro и Ultra, а единственный оставшийся путь — вход по API-ключу — требует биллинга в регионе, где Россия не числится. Ниже разбираем, как агент ставится, как устроены три способа входа, почему ни один из них не доводи...

    Иконка чипа0
    Иконка глаза242
    Иконка комментариев0
    Картинка поста Git флоу для команды разработчиков: гайд по веткам и релизам
    Иконка аватараАнтон
    Иконка календаря30 сентября 2026
    gitgit-flowкомандная работа+ 2middleИконка уровня middle

    Git флоу для команды разработчиков: гайд по веткам и релизам

    Git флоу для команды разработчиков: разбираем Git Flow, GitHub Flow и trunk-based development — как выбрать модель веток и избежать конфликтов при совместной работе.

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