Монолитный фронтенд — это нормально, пока команда небольшая и проект понятный. Но стоит вырасти до 5–10 разработчиков на одном репозитории, и начинается: конфликты в git, долгая сборка, невозможность деплоить одну фичу без регрессии в другой. Именно для таких ситуаций и появилась идея микрофронтендов.

Что это вообще такое

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

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

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

Когда это нужно

Сразу честно: микрофронтенды — это не серебряная пуля и не модный тренд, который надо внедрять везде. Это решение конкретной проблемы.

Они оправданы, если:

  • Команда большая — от 4–5 разработчиков на фронтенде, которые постоянно конфликтуют в одном репо
  • Проект долгосрочный — строите платформу на годы, не лендинг
  • Разные части сайта живут по-разному — например, маркетинговые страницы меняются еженедельно, а платёжный модуль — раз в квартал
  • Нужна изоляция ошибок — падение одного модуля не должно роняют всё приложение
  • Есть легаси — надо постепенно переписывать старый Angular на React, не останавливая разработку

Если у вас небольшой корпоративный сайт или интернет-магазин с одной командой — микрофронтенды добавят сложности без реальной пользы. Корпоративный сайт от 15 000 ₽ отлично живёт как монолит.

Как это работает технически

Есть несколько подходов к склейке микрофронтендов. Рассмотрим основные.

Iframe

Самый простой способ. Каждый модуль живёт в своём iframe. Изоляция полная, коммуникация через postMessage.

Плюсы: простота, изоляция стилей и JS. Минусы: плохой UX (скролл, роутинг, доступность), производительность, сложно передавать состояние.

На практике iframe используют редко — только там, где изоляция критична, например встроенные платёжные формы.

Webpack Module Federation

Пожалуй, самый популярный подход сейчас. Webpack 5 умеет делать так, что одно приложение (host) подгружает код из другого приложения (remote) прямо в рантайме.

Пример конфига:

// webpack.config.js — remote-приложение (корзина)
new ModuleFederationPlugin({
  name: 'cart',
  filename: 'remoteEntry.js',
  exposes: {
    './CartWidget': './src/CartWidget',
  },
  shared: ['react', 'react-dom'],
})

// webpack.config.js — host-приложение
new ModuleFederationPlugin({
  name: 'shell',
  remotes: {
    cart: 'cart@https://cart.example.com/remoteEntry.js',
  },
  shared: ['react', 'react-dom'],
})

Host подгружает компонент корзины с другого домена и рендерит как обычный React-компонент. При этом React шарится между ними — загружается один раз.

Это позволяет деплоить корзину независимо. Обновил remoteEntry.js на CDN — все пользователи получили новую версию без деплоя host-приложения.

Single-SPA

Фреймворк-оркестратор. Регистрирует несколько приложений и управляет их жизненным циклом в зависимости от роута.

import { registerApplication, start } from 'single-spa'

registerApplication({
  name: 'catalog',
  app: () => import('catalog/App'),
  activeWhen: '/catalog',
})

registerApplication({
  name: 'cart',
  app: () => import('cart/App'),
  activeWhen: '/cart',
})

start()

Подходит, когда разные части сайта — это реально разные страницы с разными командами. Часто комбинируют с Module Federation.

Compositing на сервере (SSR)

Если нужен SEO и быстрая загрузка, микрофронтенды собираются на сервере. Nginx или Node-прокси делает запросы к разным сервисам и склеивает HTML.

Это сложнее, но позволяет рендерить всё на сервере без потери SEO. Используется в крупных медиа и e-commerce платформах.

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

Когда приложение разбито на части, встаёт вопрос: как они общаются?

Основные подходы:

Custom Events — самый простой. Один модуль диспатчит событие, другой слушает:

// корзина добавила товар
window.dispatchEvent(new CustomEvent('cart:item-added', {
  detail: { productId: 42, quantity: 1 }
}))

// шапка слушает и обновляет счётчик
window.addEventListener('cart:item-added', (e) => {
  updateCartBadge(e.detail)
})

Shared state через URL — состояние в адресной строке видно всем модулям.

Общий стор — например, Redux или Zustand, вынесенный в shared-библиотеку. Работает, но создаёт зависимость между командами.

Props/callbacks через shell — host-приложение передаёт данные в remote-модули как обычные пропсы. Чисто, но shell начинает знать слишком много.

Лучший выбор зависит от частоты коммуникации. Если модули почти не общаются — Custom Events. Если постоянно — стоит подумать, правильно ли вы разбили приложение.

Стили и дизайн-система

Это один из главных подводных камней. Если каждый модуль тащит свои CSS — получите конфликты и мусор.

Решения:

  • CSS Modules или Shadow DOM — изолируют стили внутри модуля
  • CSS-переменные — шарятся через корень документа, все модули используют единый набор токенов
  • Общая библиотека компонентов — отдельный npm-пакет с UI-кит, который все импортируют

Совет: заранее инвестируйте в дизайн-систему. Без неё разные команды начнут рисовать кнопки по-разному, и через год сайт будет выглядеть как лоскутное одеяло.

Деплой и инфраструктура

Каждый микрофронтенд — отдельный артефакт со своим CI/CD. Типичный флоу:

  1. Разработчик пушит в репо команды корзины
  2. GitHub Actions запускает сборку и тесты
  3. Собранный remoteEntry.js и чанки улетают на S3 или CDN
  4. Host-приложение автоматически подхватывает новую версию

Важный момент — версионирование. Если host жёстко ссылается на remoteEntry.js без версии, новый деплой сразу попадёт к пользователям. Это удобно, но рискованно. Лучше деплоить по конкретному тегу и переключать через конфиг или feature flags.

Реальные цифры

Чтобы было понятно, о каком масштабе разговор:

  • IKEA перешла на микрофронтенды и сократила время деплоя с нескольких часов до 15 минут
  • Spotify использует микрофронтенды с 2016 года — каждый блок интерфейса за отдельную команду
  • Zalando — пионер подхода, написали один из первых открытых фреймворков Mosaic

Для небольших проектов эти цифры неактуальны — там монолит выиграет по простоте обслуживания.

Сложности, о которых не говорят

Производительность. Каждый remote — это дополнительный HTTP-запрос. Если неправильно настроить шаринг зависимостей, React загрузится несколько раз. Нужны грамотная настройка кэширования и shared-библиотек.

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

Отладка. Стектрейс из пяти разных приложений — не самое приятное. Source maps должны быть настроены для каждого модуля отдельно.

Организационная сложность. Технически это решаемо. Сложнее договориться, кто владеет общими компонентами, как согласовать breaking changes в API между командами, как синхронизировать версии зависимостей.

Микрофронтенды — это в первую очередь организационное решение, и только потом техническое.

Когда не надо

Есть соблазн разбить на микрофронтенды просто потому, что «так правильно». Не делайте этого.

Если у вас:

  • Команда до 3–4 фронтендеров
  • Стартап с нестабильными требованиями
  • Проект с агрессивными дедлайнами
  • Нет опыта с Webpack Module Federation или Single-SPA

...то монолит с хорошей модульной структурой (feature-sliced design, например) даст те же преимущества без накладных расходов.

Мы в REEXY при разработке сложных проектов всегда сначала оцениваем, оправдан ли overhead. Корпоративный портал на 50 страниц часто удобнее держать как хорошо организованный монолит, чем городить инфраструктуру под микрофронтенды.

Как начать, если решились

Если всё-таки решили идти в эту сторону — не переписывайте всё сразу. Постепенная миграция работает лучше.

  1. Выберите одну изолированную часть — например, блок отзывов или личный кабинет. То, что редко пересекается с остальными.
  2. Вынесите её в отдельное приложение с Module Federation.
  3. Обкатайте CI/CD и деплой на этом модуле.
  4. Установите конвенции: как называть события, как шарить стили, как версионировать.
  5. Постепенно выносите остальные части по мере необходимости.

Не пытайтесь разбить всё за один спринт — это провальная стратегия.

Инструменты

Что сейчас используют чаще всего:

  • Webpack 5 Module Federation — де-факто стандарт, хорошая документация, широкое сообщество
  • Vite + vite-plugin-federation — если проект на Vite, есть плагин с похожими возможностями
  • Single-SPA — хороший выбор для оркестрации, особенно при смешанных фреймворках
  • Nx — монорепо-инструмент, умеет управлять несколькими приложениями с умной пересборкой только изменившихся частей
  • Turborepo — альтернатива Nx, проще в освоении

Nx особенно полезен на старте — позволяет держать все микрофронтенды в одном репо (monorepo), но деплоить независимо. Это снижает операционную сложность на первых порах.

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