Webpack Module Federation — это революционная функция, представленная в Webpack 5, которая полностью меняет способ реализации микрофронтенд-архитектуры. Объединение модулей позволяет различным веб-приложениям (или микро-интерфейсным приложениям) динамически совместно использовать код во время выполнения без необходимости физического совместного использования во время традиционных процессов упаковки или выпуска. Это означает, что каждое микроприложение можно разрабатывать, создавать и развертывать независимо, а также легко совместно использовать компоненты, библиотеки и даже бизнес-логику.
Приложение в контейнереwebpack.config.js
середина,использоватьModuleFederationPlugin
объявить происхождение удаленного микроприложения。
// webpack.config.js (Container)
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
module.exports = {
// ...другие конфигурации
plugins: [
new ModuleFederationPlugin({
name: 'container',
remotes: {
app1: 'app1@http://localhost:3001/remoteEntry.js',
app2: 'app2@http://localhost:3002/remoteEntry.js',
},
shared: {
react: { singleton: true },
'react-dom': { singleton: true },
},
}),
],
};
здесь,remotes
Поле указывает имя удаленного микроприложения и его файл удаленной записи.URL。shared
Конфигурация определяет, какие модули следует использовать как одиночные.,Такие как React и ReactDOM.,чтобы избежать повторной загрузки.
в каждом удаленном приложенииwebpack.config.js
середина,такой жеиспользоватьModuleFederationPlugin
,Но на этот раз я здесь, чтобы показать свой модуль.
// webpack.config.js (Remote App1)
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
module.exports = {
// ...другие конфигурации
plugins: [
new ModuleFederationPlugin({
name: 'app1',
filename: 'remoteEntry.js',
exposes: {
'./MyComponent': './src/components/MyComponent',
},
shared: {
react: { singleton: true },
'react-dom': { singleton: true },
},
}),
],
};
exposes
Поля определяют, какие модули будут доступны внешнему миру.。существоватьэтот примерсередина,Компоненты MyComponent можно импортировать и использовать из контейнерных приложений или других микроприложений.
В приложении-контейнере или другом удаленном приложении удаленно доступные модули можно импортировать напрямую.
// In a component of Container or another Remote App
import MyComponent from 'app1/MyComponent';
function App() {
return (
<div>
<h1>Container App</h1>
<MyComponent />
</div>
);
}
export default App;
Объединение модулей Webpack обеспечивает эффективное и гибкое решение для разработки и обслуживания современных веб-приложений за счет упрощения механизма совместного использования кода в микрофронтенд-архитектуре.
Давайте рассмотрим простой пример, чтобы продемонстрировать, как использовать объединение модулей Webpack для создания двух микроприложений: приложения-контейнера и удаленного приложения.
Сначала создайте новое приложение React как приложение-контейнер:
npx create-react-app container-app
cd container-app
Установите webpack и webpack-cli (обратите внимание, что поскольку create-react-app уже содержит Webpack, обычно нет необходимости устанавливать его отдельно, это только в демонстрационных целях):
npm install webpack webpack-cli --save-dev
Измените package.json и добавьте сценарий запуска для настройки Webpack:
"scripts": {
"start": "webpack serve --config webpack.config.js",
// ...
}
создаватьwebpack.config.js
,КонфигурацияModule Federation Plugin
:
// webpack.config.js (Container App)
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
module.exports = {
// ...другие конфигурации
plugins: [
new HtmlWebpackPlugin({ template: './public/index.html' }),
new ModuleFederationPlugin({
name: 'containerApp',
remotes: {
remoteApp: 'remoteApp@http://localhost:3010/remoteEntry.js',
},
shared: {
react: { singleton: true },
'react-dom': { singleton: true },
},
}),
],
};
Создайте удаленное приложение в другом каталоге:
npx create-react-app remote-app
cd remote-app
такой же,Исправлятьpackage.json
,Добавить скрипт запуска,и установитьwebpack
иwebpack-cli
(Только пример):
npm install webpack webpack-cli --save-dev
существоватьremote-app
изwebpack.config.js
середина КонфигурацияModule Federation Plugin
выставить компоненты:
// webpack.config.js (Remote App)
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
module.exports = {
// ...другие конфигурации
plugins: [
new ModuleFederationPlugin({
name: 'remoteApp',
filename: 'remoteEntry.js',
exposes: {
'./MyWidget': './src/MyWidget',
},
shared: {
react: { singleton: true },
'react-dom': { singleton: true },
},
}),
],
};
существоватьremote-app/src
в каталогесоздаватьMyWidget.js
компоненты:
// MyWidget.js
import React from 'react';
const MyWidget = () => {
return <h1>Hello from Remote App!</h1>;
};
export default MyWidget;
Вернитесь в приложение-контейнер и импортируйте удаленные компоненты, где это необходимо:
// container-app/src/App.js
import React from 'react';
import MyWidget from 'remoteApp/MyWidget';
function App() {
return (
<div className="App">
<header className="App-header">
<MyWidget />
</header>
</div>
);
}
export default App;
Запустите два приложения отдельно:
# В каталоге удаленного приложения
npm start --port 3010
# В каталоге приложения-контейнера
npm start
Теперь откройте приложение-контейнер в своем браузере, и вы увидите, что компоненты удаленного приложения успешно загружаются и отображаются.
в реальных проектах,Возможно, вам захочется динамически загружать удаленное приложение в зависимости от поведения пользователя или определенных условий. Федерация модулей Webpack поддерживает асинхронную загрузку.,Толькосуществовать При импортеиспользоватьimport()
функция。
// container-app/src/App.js
import React, { lazy, Suspense } from 'react';
const MyWidget = lazy(() => import('remoteApp/MyWidget'));
function App() {
return (
<div className="App">
<Suspense fallback={<div>Loading...</div>}>
<MyWidget />
</Suspense>
</div>
);
}
export default App;
Таким образом, компонент MyWidget будет загружаться по требованию, когда это необходимо, что повышает скорость загрузки первого экрана.
В микроархитектуре внешнего интерфейса,Убедитесь, что между различными приложениямииз Совместимость версий зависимостей является ключевым моментом。использоватьModuleFederationPlugin
изshared
Конфигурация,Вы можете указать диапазоны версий и стратегии загрузки для общих модулей (например,,singleton
、strictVersion
ждать)。
// webpack.config.js
new ModuleFederationPlugin({
// ...
shared: {
react: { version: '^17.0.0', singleton: true },
'react-dom': { version: '^17.0.0', singleton: true },
},
}),
В микроархитектуре внешнего интерфейса,Управление маршрутизацией является важнымизкомпоненты。ты можешьиспользоватькартинаreact-router-dom
такиз Библиотека,объединитьMicrofrontends-Router
или индивидуализируйте решения для достижения перекрестного примененияиз Прыжок по маршруту。
// container-app/src/Routes.js
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import App1 from './App1';
import App2 from './App2';
function Routes() {
return (
<Router>
<Switch>
<Route path="/app1" component={App1} />
<Route path="/app2" component={App2} />
</Switch>
</Router>
);
}
export default Routes;
Для требований общего состояния вы можете использовать Redux, MobX или Context APIждать Управление Библиотека статусов, или специально для микровнешности интерфейсдизайниз Управление статусами Куруsingle-spa-redux
、qiankun
изstore
решениеждать。
Помимо компонентов, вы также можете делиться сервисами и публичными библиотеками. Например, создайте выделенное удаленное приложение для предоставления служб API или используйте общую библиотеку HTTP.
// webpack.config.js (Remote App for Services)
new ModuleFederationPlugin({
name: 'services',
filename: 'remoteEntry.js',
exposes: {
'./ApiService': './src/services/ApiService',
'./HttpLibrary': './src/libs/http-library',
},
shared: {
// ...другие общие библиотеки
},
}),
Чтобы обеспечить микро внешний вид интерфейсприложениеиз Стабильная работа,Необходимо реализовать глобальный перехват ошибок.ирегистрация。Можетиспользоватьwindow.onerror
、try...catch
заявление,Или используйте специализированную библиотеку журналирования, например log4js.
// container-app/src/index.js
window.onerror = function (errorMessage, fileName, lineNumber, columnNumber, error) {
// Сообщение об ошибке журнала
console.error(errorMessage, fileName, lineNumber, columnNumber, error);
// ...Другая логика обработки
return true; // Запретить обработку ошибок браузера по умолчанию
};