Module Federation: собирать не вместе.
Практическая памятка для host и remote приложений. Module Federation позволяет загружать части другого приложения во время выполнения, но не заменяет договорённости о границах, версиях и владении.
Модель
hostКонтейнер, который импортирует и отображает удалённые модули.
remoteПриложение, которое выставляет свои модули через remoteEntry.js.
exposesПубличный контракт remote: какие модули доступны другим приложениям.
remotesКарта адресов remote-модулей, которые может загрузить host.
sharedБиблиотеки, которые не нужно тащить отдельной копией в каждый remote.
Remote: конфигурация
new ModuleFederationPlugin({ name: 'catalog' })Уникальное имя контейнера remote.
filename: 'remoteEntry.js'Имя entry-файла, который host загрузит первым.
exposes: { './ProductCard': './src/ProductCard' }Выставить компонент под стабильным публичным ключом.
output: { publicPath: 'auto' }Webpack определяет базовый URL для дочерних чанков относительно загруженного remote entry.
devServer: { port: 3001 }Remote должен быть доступен host во время локальной разработки.
Host: подключение
remotes: { catalog: 'catalog@https://cdn.example.com/catalog/remoteEntry.js' }Связать имя импорта с контейнером и URL его entry-файла.
import('catalog/ProductCard')Динамический импорт remote-модуля; он загружается во время выполнения.
React.lazy(() => import('catalog/ProductCard'))Лениво подключить удалённый React-компонент.
<Suspense fallback={<Loader />}>Показать безопасное состояние, пока remote загружается.
ErrorBoundaryОтделить падение удалённого компонента от остальной страницы.
Shared-зависимости
shared: { react: { singleton: true } }Одна копия React для host и remote: важно для контекста, hooks и рендера.
react-dom: { singleton: true }То же правило для React DOM.
requiredVersion: deps.reactЗаявить совместимую версию библиотеки из package.json.
strictVersion: trueНе загружать несовместимую версию молча; ошибка лучше скрытого расхождения.
eager: trueЗагружать shared-библиотеку сразу. Используйте редко: это увеличивает initial bundle.
Контракты
exposes: { './routes': './src/routes' }Публикуйте узкий API: компонент, маршруты, адаптер или дизайн-систему, а не внутреннюю структуру папок.
export type ProductCardProps = ...Держите типы props рядом с публичной точкой входа.
@org/catalog-contractsОтдельный небольшой пакет для общих типов и схем, если их используют несколько приложений.
versioned remote URLПубликуйте immutable-версии или хэши: host должен получать согласованный набор entry и чанков.
contract testПроверяйте, что remote отдаёт ожидаемые экспорты и host умеет их загрузить.
Маршрутизация и состояние
host owns the shellHost обычно владеет шапкой, аутентификацией, top-level routing и границей ошибок.
remote owns a featureRemote владеет своими экранами, локальным состоянием и API конкретного домена.
route prefix: /catalog/*Явно закрепите пространство URL за доменом remote.
custom events / callbacksДля связи между приложениями предпочитайте узкие события и явные props глобальному store.
URL as shared stateФильтры и выбранные сущности, важные для навигации, безопаснее держать в URL.
Частые поломки
ScriptExternalLoadErrorHost не скачал remoteEntry.js: проверьте URL, CDN, CORS, CSP и доступность файла.
Shared module is not availableНе сходятся настройки shared, порядок загрузки или версии библиотек.
Invalid hook callЧаще всего на странице оказались две копии React; проверьте singleton, lockfile и алиасы.
ChunkLoadErrorEntry от одной версии пытается загрузить chunk от другой. Используйте atomic deploy и versioned assets.
remote works locally, fails in prodПроверьте publicPath: 'auto', заголовки CDN, CORS и абсолютные пути к ассетам.
Перед production
fallback UIУ каждого remote есть загрузка, ошибка и деградированный режим.
observabilityДобавьте имя remote и его версию в ошибки, логи и web-vitals.
independent deployПроверьте, что remote можно выкатить и откатить независимо, не ломая опубликованный контракт.
performance budgetИзмеряйте лишние запросы, вес remote entry и время до интерактивности.
ownershipЗаранее определите команду-владельца, SLA и путь эскалации для каждого remote.