Module Federation — механизм распределённой загрузки JavaScript-модулей, позволяющий нескольким независимым сборкам Webpack динамически подключать код друг друга во время выполнения приложения. Архитектура решает задачу разделения фронтенда на автономные части, которые могут разрабатываться, деплоиться и обновляться независимо, сохраняя при этом возможность совместного использования зависимостей.
Ключевая идея заключается в том, что одна сборка (host) может загружать модули из другой сборки (remote) без необходимости их предварительной компоновки в единый бандл на этапе build time. Это переносит интеграцию на runtime и делает возможной распределённую модульную архитектуру.
В экосистеме Module Federation выделяются два основных типа приложений:
Host (контейнер) Приложение, которое инициирует загрузку внешних модулей. Оно не содержит весь функционал, а подключает его из других сборок.
Remote (удалённый контейнер) Приложение, которое экспортирует свои модули наружу и предоставляет их для использования другим сборкам.
Одна и та же сборка может одновременно выступать и host, и remote.
Каждое remote-приложение при сборке формирует специальный контейнер —
remoteEntry.js. Это точка входа для динамического
подключения модулей.
Контейнер содержит:
Host загружает remoteEntry.js, после чего получает
доступ к публичным модулям remote-сборки.
// webpack.config.js (remote)
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
module.exports = {
mode: "development",
plugins: [
new ModuleFederationPlugin({
name: "remoteApp",
filename: "remoteEntry.js",
exposes: {
"./Button": "./src/Button",
"./utils": "./src/utils"
},
shared: {
react: { singleton: true },
"react-dom": { singleton: true }
}
})
]
};
// webpack.config.js (host)
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
module.exports = {
mode: "development",
plugins: [
new ModuleFederationPlugin({
name: "hostApp",
remotes: {
remoteApp: "remoteApp@http://localhost:3001/remoteEntry.js"
},
shared: {
react: { singleton: true },
"react-dom": { singleton: true }
}
})
]
};
При обращении к удалённому модулю происходит цепочка операций:
remoteEntry.js"./Button")Пример использования:
import("remoteApp/Button").then((module) => {
const Button = module.default;
});
Параметр exposes определяет публичный API
remote-приложения.
exposes: {
"./Header": "./src/components/Header",
"./api": "./src/services/api",
"./store": "./src/store"
}
Особенности:
Host-приложение описывает удалённые источники:
remotes: {
shop: "shop@https://cdn.example.com/shop/remoteEntry.js",
auth: "auth@https://cdn.example.com/auth/remoteEntry.js"
}
Формат строки:
[name]@[url]
где:
name — имя контейнераurl — адрес remoteEntryModule Federation позволяет разделять зависимости между приложениями, избегая дублирования библиотек.
shared: {
react: {},
"react-dom": {}
}
Для библиотек, которые должны иметь единственный экземпляр:
shared: {
react: { singleton: true },
"react-dom": { singleton: true }
}
Это критично для:
shared: {
lodash: {
requiredVersion: "^4.17.21",
strictVersion: true
}
}
Поведение:
shared: {
react: {
eager: true
}
}
Особенности:
Module Federation поддерживает динамическую регистрацию remote во время выполнения.
__webpack_init_sharing__("default");
const container = window.remoteApp;
await container.init(__webpack_share_scopes__.default);
const factory = await container.get("./Button");
const Module = factory();
Это позволяет:
Одной из ключевых проблем распределённых фронтендов является контроль версий.
Webpack сравнивает:
При конфликте применяется стратегия:
Module Federation не требует полного единства технологий между приложениями, но накладывает ограничения:
Изоляция достигается за счёт:
const Dashboard = React.lazy(() => import("dashboard/App"));
Преимущества:
remoteEntry.js кэшируется браузером как обычный
JS-ресурс.
Практика:
Remote-приложение сохраняет собственную стратегию splitChunks, но влияет на:
Module Federation часто используется для реализации микрофронтендов:
1. Container not found
2. Shared module conflict
3. Chunk loading error
stats: {
federation: true
}
Позволяет анализировать:
Module Federation добавляет runtime-доступ к внешнему коду, что требует контроля: