Микрофронтенды и монорепо часто путают, хотя они решают разные задачи. Монорепо это способ хранить код. Микрофронтенды это способ делить приложение на независимо разворачиваемые части. Можно иметь одно без другого.
Микрофронтенды
Идея: большое приложение режется по бизнес-доменам (каталог, корзина, профиль), каждую часть ведёт своя команда, у каждой свой цикл релизов. Главная ценность организационная: команды не ждут друг друга при деплое.
Когда оправданы:
- много команд (условно 5+) на одном продукте мешают друг другу в релизах;
- нужно постепенно переписать легаси (паттерн strangler fig: новые части рядом со старой);
- части продукта действительно независимы.
Когда не нужны: одна-две команды, маленький продукт. Тогда это лишняя сложность: общий дизайн, версии зависимостей, производительность, отладка.
Способы интеграции
| Способ | Как работает | Плюсы и минусы |
|---|---|---|
| На этапе сборки (npm-пакеты) | части публикуются пакетами и собираются в одно приложение | просто, но деплой общий: это не настоящие микрофронтенды |
| iframe | каждая часть в своём фрейме | полная изоляция, но тяжело: свой контекст, проблемы с размерами, роутингом, доступностью |
| Module Federation | приложение в рантайме грузит модули другого по URL | независимый деплой, общие зависимости; сложнее отладка и версии |
| Web Components | части оформлены как custom elements | фреймворконезависимо, изоляция стилей через Shadow DOM |
| Серверная композиция | страница собирается из фрагментов на сервере или CDN (SSI, ESI) | быстрый первый экран, но сложная инфраструктура |
| Оркестратор (single-spa) | корневое приложение монтирует части по маршруту | можно смешивать фреймворки |
Module Federation
Появилась в Webpack 5, сейчас развивается как Module Federation 2.0 отдельно от сборщика (пакеты @module-federation/*), работает с Webpack, Rspack и через плагины с Vite.
- host (shell) загружает удалённые модули;
- remote публикует модули, описывает их в
exposes; - клиент получает манифест или
remoteEntry.jsи грузит чанки в рантайме; sharedобъявляет общие зависимости (React), чтобы не грузить их дважды;singleton: trueгарантирует одну копию, это критично для React и контекстов.
// remote
new ModuleFederationPlugin({
name: 'cart',
exposes: { './CartWidget': './src/CartWidget' },
shared: { react: { singleton: true }, 'react-dom': { singleton: true } },
});
// host
remotes: { cart: 'cart@https://cdn.example.ru/cart/remoteEntry.js' }
Проблемы микрофронтендов
- Общие зависимости: две версии React на странице ломают хуки и контексты.
- Стили: конфликты классов. Решают CSS Modules, префиксы, Shadow DOM.
- Связь между частями: через события (
CustomEvent), URL или маленькую шину, а не общий глобальный стор. - Единый дизайн: общий UI-кит пакетом с версиями.
- Производительность: лишние запросы и дубли кода.
- Отказоустойчивость: если remote не загрузился, хост показывает заглушку (Error Boundary), а не падает целиком.
Монорепо
Один репозиторий для нескольких пакетов и приложений. Плюсы: атомарные изменения в нескольких пакетах одним PR, общие конфиги, проще рефакторинг. Минусы: тяжелее CI без кеша, нужна дисциплина границ.
Инструменты:
- pnpm workspaces (или npm, yarn workspaces): связывают пакеты локально;
- Turborepo: запуск задач по графу зависимостей, локальный и удалённый кеш результатов;
- Nx: то же плюс генераторы,
affected(запустить только затронутое), правила границ между проектами.
Ключевая идея: CI запускает сборку и тесты только для пакетов, затронутых изменением, и берёт остальное из кеша.
Частые ошибки
- Делать микрофронтенды «потому что модно» при одной команде.
- Нарезать по техническим слоям (шапка, футер), а не по доменам.
- Общий глобальный стор между микрофронтендами: возвращает жёсткую связность.
- Не задать
singletonдля React в Module Federation.
Что спросят на собесе
- Какие проблемы решают микрофронтенды и когда они не нужны?
- Какие способы интеграции знаешь? Плюсы и минусы.
- Как работает Module Federation, что такое shared и singleton?
- Как микрофронтенды общаются между собой?
- Чем монорепо отличается от микрофронтендов, зачем Nx или Turborepo?