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

Ваш монолитный фронтенд разросся до 300 тысяч строк кода. Три команды работают над одним репозиторием — и каждый выпуск превращается в русскую рулетку. Конфликты слияния, регрессы в соседних модулях, недельные ревью кода. А потом маркетинг просит заменить главную страницу за три дня — и вся команда понимает, что это невозможно.
Микрофронтенды решают проблему, которую бэкенд решил микросервисами лет пять назад: разбить монолит на независимые части. Каждую можно разрабатывать, тестировать и выкатывать отдельно. Разные технологии, разные команды, разные выпуски — но для пользователя это одно приложение. Звучит как панацея. На деле — архитектурная сложность, которая окупается только при определённом масштабе.
В этом материале разберём, как устроены микрофронтенды, когда они действительно нужны, а когда создадут больше проблем, чем решат. И как подойти к миграции, если вы уже столкнулись с болью монолита.
Микрофронтенд — это когда одно веб-приложение собрано из нескольких независимых фронтенд-приложений. Каждое живёт в своём репозитории, имеет свой конвейер сборки, свою команду. На уровне браузера они собираются в единый интерфейс — через iframe, Web Components, динамическую подгрузку сборок или server-side composition.

В монолите всё лежит в одном репозитории. Одна сборка, одно развёртывание. Изменил компонент в корзине — пересобрал весь проект, прогнал тесты для каталога, личного кабинета, оформления заказа. В микрофронтендах корзина — отдельное приложение. Команда выкатывает новую версию корзины — остальные модули даже не знают.
Разница не в том, как разбит код внутри. Разница в границах ответственности. В монолите один package.json, одна версия React, одна команда владеет всем. В микрофронтендах каждый модуль решает сам: React 18 или Vue 3, TypeScript или нет, какие библиотеки подключать. Это автономия. И одновременно риск, что в продакшене окажется три версии одной и той же библиотеки.
Технически микрофронтенды можно реализовать несколькими способами. Server-side composition — сервер собирает HTML из кусков, отданных разными приложениями. Build-time integration — модули публикуются как npm-пакеты, основное приложение подтягивает их при сборке. Runtime integration — браузер загружает модули по требованию: через Module Federation в Webpack 5, SystemJS или даже обычные script-теги. Последний вариант самый гибкий: можно выкатить обновление одного модуля без пересборки остальных. Но и самый сложный в отладке — ошибки всплывают только в рантайме, когда модули уже интегрированы в браузере пользователя.
Монолит проще. Один репозиторий, одна команда, один процесс. Для стартапа или продукта с двумя-тремя разработчиками это правильный выбор. Микрофронтенды начинают окупаться, когда команд больше трёх, а бизнес требует независимых выпусков.
Сценарий 1: несколько команд работают над одним продуктом
У вас интернет-магазин. Одна команда отвечает за каталог, вторая — за корзину и оформление заказа, третья — за личный кабинет. В монолите они конкурируют за доступ к кодовой базе. Ревью кода растягивается на неделю, потому что нужно проверить, не сломали ли изменения в корзине фильтры в каталоге. В микрофронтендах каждая команда владеет своим модулем. Выкатывает версии независимо. Оформление заказа обновили в понедельник — каталог остался нетронутым.
Сценарий 2: необходимость использовать разные технологии
Вы наняли новую команду, они эксперты в Vue. Старый фронтенд на React — и никто не хочет переписывать с нуля. Микрофронтенды позволяют внедрить Vue-модуль в React-приложение. Новый личный кабинет на Vue живёт рядом с каталогом на React. Пользователь не замечает разницы. Главное — договориться о shared state и событиях между модулями. Иначе получите зоопарк технологий, где каждый модуль управляет состоянием по-своему, и они не могут нормально общаться.
Сценарий 3: миграция с legacy на новый стек
Старый фронтенд на Angular.js или Backbone. Переписать целиком — полгода работы и высокий риск. Микрофронтенды дают возможность мигрировать по частям. Начинаете с нового модуля — например, личного кабинета на React. Старое приложение продолжает работать. Постепенно переносите остальные части. Для бизнеса это незаметно — пользователи видят обновления, но без остановки продукта.
Сценарий 4: белые метки и B2B-платформы
У вас SaaS-платформа для строительных компаний — как в проекте ADP, который мы делали для B2B. Каждый клиент хочет кастомизацию: свои цвета, логотипы, иногда уникальные модули. В монолите пришлось бы поддерживать ветки кода для каждого клиента. В микрофронтендах базовые модули общие — диаграмма Ганта, Kanban, управление задачами. А кастомные части собираются по запросу: для одного клиента включаем модуль закупок, для другого — интеграцию с 1С. Это работает, если правильно организовать композицию — иначе каждый клиент начнёт требовать свою сборку, и вы утонете в ошибках совместимости.
Сценарий 5: высокие требования к скорости загрузки
Крупный портал с десятками разделов. Пользователю нужна только личная лента — но монолит грузит весь JavaScript сразу. В микрофронтендах загружаются только нужные модули. Зашёл в личный кабинет — подгрузился только его бандл. Перешёл в каталог — подтянулся модуль каталога. Это снижает initial bundle size и ускоряет First Contentful Paint. Именно так мы настроили окружение для B2C-платформы экосистемы BabyDoge: развернули Vite, оптимизировали Cold Start и HMR. Для пользователей платформа стала быстрым и отзывчивым инструментом, который мгновенно загружается даже на мобильных.
Во всех остальных случаях микрофронтенды — это избыточная архитектура. Если команда одна, выгода от независимых выпусков равна нулю.
Независимые выпуски — главное, ради чего всё затевается. Команда каталога выкатывает функцию в понедельник. Команда корзины — в среду. Команда личного кабинета — в пятницу. Никто не ждёт общего выпуска. Это критично для крупных продуктов, где функции должны выходить быстро, а регресс в одном модуле не может блокировать выпуск другого.
Изоляция отказов. Если один микрофронтенд упал — остальные продолжают работать. Каталог сломался — но корзина и оформление заказа работают, пользователь может оформить заказ. В монолите один некорректный import — и весь фронтенд не соберётся.
Гибкость в технологиях. Можете использовать React для каталога, Vue для личного кабинета, Svelte для админки. Для команд, которые приходят с разным опытом, это снижает порог входа. Но это и риск: если не следить за общей архитектурой, получите зоопарк, где каждый модуль живёт в своём мире.
Масштабируемость команды. В монолите больше трёх-четырёх разработчиков начинают наступать друг другу на ноги. В микрофронтендах каждая команда работает в своём модуле, со своим списком задач, своими приоритетами. Масштабируете команду — добавляете новый модуль. Не нужно координировать весь фронтенд.
Сложность интеграции. Модули должны уметь общаться: передавать данные, синхронизировать состояние, реагировать на события. Если один модуль обновил корзину, другой должен узнать об этом. Реализовать это на уровне браузера непросто: нужен единый event bus, shared state, договорённости о форматах данных. В монолите это просто общий Redux store. В микрофронтендах — custom events, postMessage, глобальный объект или библиотеки вроде single-spa.
Дублирование кода и зависимостей. Каждый модуль может подтянуть свою версию React, свою версию UI-библиотеки. Если не настроить shared dependencies, пользователь скачает React три раза. Это убивает производительность. Webpack Module Federation решает проблему — но его нужно правильно настроить, иначе получите runtime-ошибки, когда модули не могут найти нужную версию библиотеки.
Отладка и мониторинг. В монолите ошибка видна в одном месте. В микрофронтендах ошибка может всплыть в модуле, который загружается динамически — и source map не подтянется, потому что он лежит на другом CDN. Нужна централизованная система мониторинга: Sentry, LogRocket или аналоги. И договорённости о том, как логировать ошибки, чтобы понимать, в каком модуле проблема.
Накладные расходы на инфраструктуру. Для каждого микрофронтенда — свой CI/CD, свой конвейер, своё развёртывание. Это больше работы для DevOps. Больше времени на настройку окружения, больше точек отказа. В монолите одно развёртывание — в микрофронтендах три-четыре.
Риск фрагментации UX. Если каждая команда разрабатывает свой модуль независимо, может получиться так, что каталог выглядит в одном стиле, корзина — в другом. Нужна жёсткая design system и shared UI-компоненты. Иначе пользователь увидит разнородный интерфейс.
Микрофронтенды окупаются, когда выгода от независимых выпусков и масштабирования команды перевешивает архитектурную сложность. Для стартапа с одной командой это лишние проблемы.
Позволяет динамически загружать модули из разных сборок в runtime. Один микрофронтенд экспортирует компоненты, другой импортирует их прямо в браузере. Можно расшарить зависимости — React, UI-библиотеки — чтобы не дублировать их в каждом бандле. Это решает проблему размера и позволяет обновлять модули независимо. Но есть нюанс: если версии зависимостей не совпадают, будет runtime-ошибка. Нужно чётко договариваться о версиях или использовать semver-совместимость.
Микрофреймворк для оркестрации микрофронтендов. Работает как роутер: определяет, какой модуль нужно показать в зависимости от URL. Поддерживает React, Vue, Angular — можно комбинировать. Предоставляет lifecycle-хуки для загрузки, монтирования и размонтирования модулей. Хорошо подходит для миграции: можно постепенно переносить части монолита, не трогая остальное.
Нативная браузерная технология. Каждый микрофронтенд — это кастомный элемент, инкапсулированный в Shadow DOM. Работает без фреймворков, можно встроить в любое окружение. Но Shadow DOM создаёт изоляцию стилей — иногда это плюс, иногда проблема, если нужно применить глобальные стили. И не все команды готовы писать на ванильном JS — большинство привыкли к React или Vue.
Сервер собирает HTML из фрагментов, которые отдают разные микрофронтенды. Для пользователя это работает быстрее: не нужно ждать загрузки JS, страница рендерится на сервере. Но сложность переносится на бэкенд — нужна инфраструктура для запросов к микрофронтендам, кеширования, обработки ошибок. Подходит для контент-ориентированных проектов — порталов, медиа.
Для проектов с высокими требованиями к скорости разработки. Vite использует нативные ES-модули, что даёт мгновенный Cold Start и быстрый HMR. Мы развернули Vite для B2C-платформы BabyDoge — это дало моментальную загрузку даже на мобильных. Turbopack от Vercel — конкурент, пока в beta, но обещает ещё большую скорость за счёт Rust-based архитектуры.
Чтобы модули выглядели единообразно, нужна централизованная UI-библиотека. React-компоненты, стили, иконки — всё должно быть в одном месте. Публикуете как npm-пакет, каждый микрофронтенд подключает нужную версию. Если не сделать этого сразу, каждая команда начнёт писать свои кнопки, формы, модалки — и продукт превратится в лоскутное одеяло.
Выбор инструментов зависит от масштаба. Для начала подойдёт Module Federation или single-spa. Если нужна SSR-производительность — server-side composition. Если команда готова к нативным технологиям — Web Components.
Действительно ли монолит создаёт проблемы? Если команда одна, выпуски раз в месяц, код укладывается в 50 тысяч строк — микрофронтенды не нужны. Окупаются они, когда команд больше двух, выпуски должны идти независимо, и монолит уже начинает тормозить разработку. Запустите эксперимент: попробуйте оценить, сколько времени уходит на координацию выпусков, сколько регрессов появляется из-за конфликтов в коде, сколько задач блокируются, потому что кто-то занял ветку. Если больше 20% времени — пора задуматься.
Разбейте приложение на логические домены. Каталог, корзина, личный кабинет, админка — каждый домен должен быть относительно независимым. Если модули сильно связаны (каталог напрямую меняет состояние корзины через десять уровней вложенности), придётся сначала рефакторить монолит. Нарисуйте граф зависимостей: какие модули обращаются к каким данным, какие компоненты переиспользуются. Если граф выглядит как спагетти — начните с распутывания.
До того, как начнёте выделять микрофронтенды, договоритесь об общих вещах: UI-библиотека, аутентификация, роутинг, event bus. Если каждый модуль будет решать это по-своему, получите зоопарк. Создайте npm-пакет с UI-компонентами, настройте shared dependencies в Webpack, договоритесь о формате событий. Это скучная работа, но без неё интеграция превратится в ад.
Начните с чего-то изолированного: личный кабинет, админка, модуль уведомлений. Не трогайте сразу ключевую функциональность — каталог или корзину. Вынесите выбранный модуль в отдельный репозиторий, настройте сборку, подключите к основному приложению через Module Federation или iframe. Проверьте, как работает интеграция, как передаются данные, как обрабатываются ошибки. Если всё работает — двигайтесь дальше.
Каждый микрофронтенд должен иметь свой конвейер. Отдельный репозиторий, отдельные тесты, отдельное развёртывание. Настройте автоматическое тестирование: unit, integration, e2e. Если модуль сломается — это не должно блокировать выпуск остальных. Настройте мониторинг: каждый модуль должен логировать ошибки в централизованную систему. Sentry, LogRocket или аналоги. Иначе не поймёте, где проблема, когда пользователь пожалуется.
Переносите по одному модулю за спринт. Не пытайтесь переписать всё за раз — это провал. После каждого модуля проверяйте интеграцию, исправляйте ошибки, обновляйте документацию. Когда останется только shell-приложение (роутер и общая обёртка), можете считать миграцию завершённой.
После миграции начинается рутина. Следите за размером бандлов: если каждый модуль тянет свою версию React, пользователь скачает три копии. Настройте shared dependencies. Следите за производительностью: используйте Lighthouse, Web Vitals. Если LCP (Largest Contentful Paint) начал расти — значит, где-то модуль загружается неоптимально. Настройте lazy loading для модулей, которые не нужны сразу.
Миграция занимает от трёх месяцев до полугода, в зависимости от размера монолита. Планируйте так, чтобы бизнес не остановился: каждый этап должен давать работающий продукт, а не сломанную половину приложения.
Нужно ли переписывать всё с нуля?
Нет. Микрофронтенды можно внедрять постепенно. Начните с одного модуля — например, личного кабинета. Остальное приложение остаётся монолитом. Постепенно переносите части. Это называется strangler fig pattern — новое приложение обрастает вокруг старого, пока полностью не заменит его.
Как избежать дублирования зависимостей?
Используйте Module Federation или single-spa с настройкой shared dependencies. Укажите, что React, UI-библиотека и другие крупные зависимости должны грузиться один раз. Если версии совпадают — модули используют одну копию. Если нет — загрузятся обе, но хотя бы не три.
Что делать с аутентификацией?
Аутентификация должна быть централизованной. Токены, сессии, refresh-logic — всё в одном месте, обычно в shell-приложении или shared-библиотеке. Каждый микрофронтенд обращается к общему auth-сервису. Если каждый модуль будет хранить токены по-своему, получите дыру в безопасности.
Как тестировать микрофронтенды?
Каждый модуль тестируется отдельно: unit, integration, e2e. Но нужны ещё интеграционные тесты на уровне всего приложения: проверить, что модули правильно общаются, что события передаются, что стили не конфликтуют. Используйте Cypress или Playwright для e2e, запускайте тесты в окружении, максимально близком к продакшену.
Можно ли использовать разные версии одной библиотеки?
Технически — да, но это плохая идея. Если один модуль на React 17, другой на React 18, будет две копии React в бандле. Это увеличивает размер, замедляет загрузку. Лучше договориться о единой версии или использовать peer dependencies.
Как организовать роутинг?
Роутинг живёт в shell-приложении. Оно решает, какой микрофронтенд показать в зависимости от URL. Если пользователь перешёл на /catalog, загружается модуль каталога. Если на /profile — модуль личного кабинета. Single-SPA предоставляет готовый роутер. Можно написать свой — но зачем, если есть рабочее решение.
Микрофронтенды — не панацея. Они решают проблемы крупных продуктов: независимые выпуски, масштабирование команды, изоляцию отказов. Но добавляют архитектурную сложность. Если у вас одна команда и монолит на 50 тысяч строк — оставайтесь на монолите. Если команд три, выпуски конфликтуют, а каждое слияние превращается в недельный квест — подумайте о миграции. Начните с одного модуля, проверьте гипотезу, настройте CI/CD. И только потом переносите остальное. Архитектура должна решать бизнес-задачи, а не создавать новые.
