Огляд розширеної архітектури мікрофронтендів з JavaScript Module Federation у Webpack 5. Створюйте масштабовані, підтримувані та незалежні додатки.
JavaScript Module Federation у Webpack 5: Розширена архітектура мікрофронтендів
У сучасному світі веб-розробки, що стрімко розвивається, створення великих і складних додатків може стати значним викликом. Традиційні монолітні архітектури часто призводять до кодових баз, які важко підтримувати, масштабувати та розгортати. Мікрофронтенди пропонують переконливу альтернативу, розбиваючи ці великі додатки на менші, незалежно розгортані частини. JavaScript Module Federation, потужна функція, представлена у Webpack 5, надає елегантний та ефективний спосіб реалізації архітектур мікрофронтендів.
Що таке мікрофронтенди?
Мікрофронтенди — це архітектурний підхід, за якого один веб-додаток складається з кількох менших, незалежних додатків. Кожен мікрофронтенд може розроблятися, розгортатися та підтримуватися окремими командами, що забезпечує більшу автономію та швидші цикли ітерацій. Цей підхід віддзеркалює принципи мікросервісів у світі бекенду, приносячи аналогічні переваги на фронтенд.
Ключові характеристики мікрофронтендів:
- Незалежне розгортання: Кожен мікрофронтенд можна розгортати незалежно, не впливаючи на інші частини додатка.
- Технологічна різноманітність: Різні команди можуть обирати технології та фреймворки, що найкраще відповідають їхнім потребам, сприяючи інноваціям та використанню спеціалізованих навичок.
- Автономні команди: Кожен мікрофронтенд належить окремій команді, що сприяє відповідальності та залученості.
- Ізоляція: Мікрофронтенди мають бути ізольовані один від одного, щоб мінімізувати залежності та запобігти каскадним збоям.
Знайомство з JavaScript Module Federation
Module Federation — це функція Webpack 5, яка дозволяє JavaScript-додаткам динамічно обмінюватися кодом і залежностями під час виконання. Вона дає можливість різним додаткам (або мікрофронтендам) експортувати та споживати модулі один одного, створюючи безшовний досвід інтеграції для користувача.
Ключові концепції Module Federation:
- Host (Хост): Додаток-хост — це основний додаток, який керує мікрофронтендами. Він споживає модулі, надані віддаленими додатками.
- Remote (Віддалений): Віддалений додаток — це мікрофронтенд, який надає свої модулі для споживання іншими додатками (включаючи хост).
- Shared Modules (Спільні модулі): Модулі, які використовуються як хостом, так і віддаленими додатками. Webpack може оптимізувати ці спільні модулі, щоб уникнути дублювання та зменшити розмір бандла.
Налаштування Module Federation у Webpack 5
Для реалізації Module Federation необхідно налаштувати Webpack як у хост-додатку, так і у віддалених додатках. Ось покрокова інструкція:
1. Встановіть Webpack та пов'язані залежності:
Спочатку переконайтеся, що у ваших хост- та віддалених проєктах встановлено Webpack 5 та необхідні плагіни.
npm install webpack webpack-cli webpack-dev-server --save-dev
2. Налаштуйте хост-додаток:
У файлі webpack.config.js хост-додатка додайте ModuleFederationPlugin:
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
const path = require('path');
module.exports = {
mode: 'development',
devtool: 'source-map',
entry: './src/index',
output: {
publicPath: 'http://localhost:3000/',
},
devServer: {
port: 3000,
hot: true,
historyApiFallback: true, // For single page application routing
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react']
}
}
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
},
plugins: [
new ModuleFederationPlugin({
name: 'Host',
filename: 'remoteEntry.js',
remotes: {
// Define remotes here, e.g., 'RemoteApp': 'RemoteApp@http://localhost:3001/remoteEntry.js'
'RemoteApp': 'RemoteApp@http://localhost:3001/remoteEntry.js'
},
shared: {
react: { singleton: true, requiredVersion: '^17.0.0' },
'react-dom': { singleton: true, requiredVersion: '^17.0.0' },
// Add other shared dependencies here
},
}),
// ... other plugins
],
};
Пояснення:
name: Назва хост-додатка.filename: Назва файлу, який буде надавати модулі хоста. ЗазвичайremoteEntry.js.remotes: Відображення назв віддалених додатків на їхні URL-адреси. Формат:{RemoteAppName: 'RemoteAppName@URL/remoteEntry.js'}.shared: Список модулів, які мають бути спільними для хоста та віддалених додатків. Використанняsingleton: trueгарантує, що завантажується лише один екземпляр спільного модуля. ВказанняrequiredVersionдопомагає уникнути конфліктів версій.
3. Налаштуйте віддалений додаток:
Аналогічно налаштуйте webpack.config.js віддаленого додатка:
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
const path = require('path');
module.exports = {
mode: 'development',
devtool: 'source-map',
entry: './src/index',
output: {
publicPath: 'http://localhost:3001/',
},
devServer: {
port: 3001,
hot: true,
historyApiFallback: true, // For single page application routing
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react']
}
}
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
},
plugins: [
new ModuleFederationPlugin({
name: 'RemoteApp',
filename: 'remoteEntry.js',
exposes: {
'./Widget': './src/Widget',
// Add other exposed modules here
},
shared: {
react: { singleton: true, requiredVersion: '^17.0.0' },
'react-dom': { singleton: true, requiredVersion: '^17.0.0' },
// Add other shared dependencies here
},
}),
// ... other plugins
],
};
Пояснення:
name: Назва віддаленого додатка.filename: Назва файлу, який буде надавати модулі віддаленого додатка.exposes: Відображення назв модулів на їхні шляхи у віддаленому додатку. Це визначає, які модулі можуть споживатися іншими додатками. Наприклад,'./Widget': './src/Widget'надає компонентWidget, розташований у./src/Widget.js.shared: Так само, як і в конфігурації хоста.
4. Створіть модуль для експорту у віддаленому додатку:
У віддаленому додатку створіть модуль, який ви хочете надати. Наприклад, створіть файл з назвою src/Widget.js:
import React from 'react';
const Widget = () => {
return (
Remote Widget
This is a widget from the RemoteApp.
);
};
export default Widget;
5. Споживайте віддалений модуль у хост-додатку:
У хост-додатку імпортуйте віддалений модуль за допомогою динамічного імпорту. Це гарантує, що модуль буде завантажено під час виконання.
import React, { useState, useEffect } from 'react';
const RemoteWidget = React.lazy(() => import('RemoteApp/Widget'));
const App = () => {
const [isWidgetLoaded, setIsWidgetLoaded] = useState(false);
useEffect(() => {
setIsWidgetLoaded(true);
}, []);
return (
Host Application
This is the host application.
{isWidgetLoaded ? (
Loading Widget... }>
) : (
Loading...
)}
Пояснення:
React.lazy(() => import('RemoteApp/Widget')): Це динамічно імпортує модульWidgetзRemoteApp. НазваRemoteAppвідповідає назві, визначеній у секціїremotesконфігурації Webpack хоста.Widgetвідповідає назві модуля, визначеній у секціїexposesконфігурації Webpack віддаленого додатка.React.Suspense: Використовується для обробки асинхронного завантаження віддаленого модуля. Пропсfallbackвказує компонент, який буде відображатися під час завантаження модуля.
6. Запустіть додатки:
Запустіть як хост-, так і віддалений додатки за допомогою npm start (або вашого бажаного методу). Переконайтеся, що віддалений додаток запущено *перед* хост-додатком.
Тепер ви повинні побачити віддалений віджет, відображений у хост-додатку.
Розширені техніки Module Federation
Окрім базового налаштування, Module Federation пропонує кілька розширених технік для створення складних архітектур мікрофронтендів.
1. Керування версіями та спільне використання:
Ефективне керування спільними залежностями є вирішальним для підтримки стабільності та уникнення конфліктів. Module Federation надає механізми для вказання діапазонів версій та синглтон-екземплярів спільних модулів. Використання властивості shared у конфігурації Webpack дозволяє контролювати, як завантажуються та керуються спільні модулі.
Приклад:
shared: {
react: { singleton: true, requiredVersion: '^17.0.0' },
'react-dom': { singleton: true, requiredVersion: '^17.0.0' },
lodash: { eager: true, version: '4.17.21' }
}
singleton: true: Гарантує, що завантажується лише один екземпляр модуля, запобігаючи дублюванню та зменшуючи розмір бандла. Це особливо важливо для таких бібліотек, як React та ReactDOM.requiredVersion: Вказує діапазон версій, який вимагає додаток. Webpack спробує завантажити сумісну версію модуля.eager: true: Завантажує модуль негайно, а не відкладено. Це може покращити продуктивність у деяких випадках, але також може збільшити початковий розмір бандла.
2. Динамічна Module Federation:
Замість жорсткого кодування URL-адрес віддалених додатків, ви можете динамічно завантажувати їх з конфігураційного файлу або кінцевої точки API. Це дозволяє оновлювати архітектуру мікрофронтендів без повторного розгортання хост-додатка.
Приклад:
Створіть конфігураційний файл (наприклад, remote-config.json), який містить URL-адреси віддалених додатків:
{
"RemoteApp": "http://localhost:3001/remoteEntry.js",
"AnotherRemoteApp": "http://localhost:3002/remoteEntry.js"
}
У хост-додатку отримайте конфігураційний файл і динамічно створіть об'єкт remotes:
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
const path = require('path');
const fs = require('fs');
module.exports = {
// ... other configurations
plugins: [
new ModuleFederationPlugin({
name: 'Host',
filename: 'remoteEntry.js',
remotes: new Promise(resolve => {
fs.readFile(path.resolve(__dirname, 'remote-config.json'), (err, data) => {
if (err) {
console.error('Error reading remote-config.json:', err);
resolve({});
} else {
try {
const remotesConfig = JSON.parse(data.toString());
resolve(remotesConfig);
} catch (parseError) {
console.error('Error parsing remote-config.json:', parseError);
resolve({});
}
}
});
}),
shared: {
react: { singleton: true, requiredVersion: '^17.0.0' },
'react-dom': { singleton: true, requiredVersion: '^17.0.0' },
// Add other shared dependencies here
},
}),
// ... other plugins
],
};
Важлива примітка: Розгляньте використання більш надійного методу для отримання віддаленої конфігурації в продакшн-середовищі, наприклад, кінцевої точки API або спеціалізованого сервісу конфігурації. Наведений вище приклад використовує fs.readFile для простоти, але це, як правило, не підходить для продакшн-розгортань.
3. Кастомні стратегії завантаження:
Module Federation дозволяє налаштовувати спосіб завантаження віддалених модулів. Ви можете реалізувати власні стратегії завантаження для оптимізації продуктивності або обробки специфічних сценаріїв, таких як завантаження модулів з CDN або використання service worker.
Webpack надає хуки, які дозволяють перехоплювати та змінювати процес завантаження модулів. Це забезпечує детальний контроль над тим, як отримуються та ініціалізуються віддалені модулі.
4. Робота з CSS та стилями:
Спільне використання CSS та стилів між мікрофронтендами може бути складним. Module Federation підтримує різні підходи до роботи зі стилями, зокрема:
- CSS Modules: Використовуйте CSS Modules для інкапсуляції стилів у кожному мікрофронтенді, запобігаючи конфліктам та забезпечуючи узгодженість.
- Styled Components: Використовуйте styled components або інші бібліотеки CSS-in-JS для управління стилями безпосередньо в компонентах.
- Глобальні стилі: Завантажуйте глобальні стилі зі спільної бібліотеки або CDN. Будьте обережні з цим підходом, оскільки він може призвести до конфліктів, якщо стилі не мають належних просторів імен.
Приклад використання CSS Modules:
Налаштуйте Webpack для використання CSS Modules:
module: {
rules: [
{
test: /\.module\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: {
localIdentName: '[name]__[local]--[hash:base64:5]',
},
importLoaders: 1,
},
},
'postcss-loader',
],
},
// ... other rules
],
}
Імпортуйте CSS Modules у ваших компонентах:
import React from 'react';
import styles from './Widget.module.css';
const Widget = () => {
return (
Remote Widget
This is a widget from the RemoteApp.
);
};
export default Widget;
5. Комунікація між мікрофронтендами:
Мікрофронтендам часто потрібно спілкуватися один з одним для обміну даними або виклику дій. Існує кілька способів досягти цього:
- Спільні події: Використовуйте глобальну шину подій для публікації та підписки на події. Це дозволяє мікрофронтендам спілкуватися асинхронно без прямих залежностей.
- Користувацькі події: Використовуйте користувацькі події DOM для комунікації між мікрофронтендами на одній сторінці.
- Спільне управління станом: Використовуйте спільну бібліотеку управління станом (наприклад, Redux, Zustand) для централізації стану та полегшення обміну даними.
- Прямі імпорти модулів: Якщо мікрофронтенди тісно пов'язані, ви можете імпортувати модулі безпосередньо один з одного за допомогою Module Federation. Однак цей підхід слід використовувати з обережністю, щоб уникнути створення залежностей, які підривають переваги мікрофронтендів.
- API та сервіси: Мікрофронтенди можуть спілкуватися один з одним через API та сервіси, що забезпечує слабку зв'язаність та більшу гнучкість. Це особливо корисно, коли мікрофронтенди розгорнуті на різних доменах або мають різні вимоги до безпеки.
Переваги використання Module Federation для мікрофронтендів
- Покращена масштабованість: Мікрофронтенди можна масштабувати незалежно, що дозволяє розподіляти ресурси туди, де вони найбільше потрібні.
- Підвищена підтримуваність: Менші кодові бази легше розуміти та підтримувати, що зменшує ризик помилок та підвищує продуктивність розробників.
- Швидші цикли розгортання: Мікрофронтенди можна розгортати незалежно, що дозволяє швидше ітерувати та випускати нові функції.
- Технологічна різноманітність: Команди можуть обирати технології та фреймворки, що найкраще відповідають їхнім потребам, сприяючи інноваціям та використанню спеціалізованих навичок.
- Покращена автономія команд: Кожен мікрофронтенд належить окремій команді, що сприяє відповідальності та залученості.
- Спрощений онбординг: Нові розробники можуть швидко освоїтися в менших, більш керованих кодових базах.
Виклики при використанні Module Federation
- Підвищена складність: Архітектури мікрофронтендів можуть бути складнішими за традиційні монолітні архітектури, вимагаючи ретельного планування та координації.
- Керування спільними залежностями: Управління спільними залежностями може бути складним, особливо коли різні мікрофронтенди використовують різні версії однієї бібліотеки.
- Накладні витрати на комунікацію: Комунікація між мікрофронтендами може створювати додаткові навантаження та затримки.
- Інтеграційне тестування: Тестування інтеграції мікрофронтендів може бути складнішим, ніж тестування монолітного додатка.
- Накладні витрати на початкове налаштування: Налаштування Module Federation та початкової інфраструктури може вимагати значних зусиль.
Реальні приклади та випадки використання
Module Federation використовується все більшою кількістю компаній для створення великих, складних веб-додатків. Ось кілька реальних прикладів та випадків використання:
- Платформи електронної комерції: Великі платформи електронної комерції часто використовують мікрофронтенди для управління різними частинами веб-сайту, такими як каталог товарів, кошик та процес оформлення замовлення. Наприклад, німецький ритейлер може використовувати окремий мікрофронтенд для відображення товарів німецькою мовою, тоді як французький — інший мікрофронтенд для французьких товарів, обидва інтегровані в один хост-додаток.
- Фінансові установи: Банки та фінансові установи використовують мікрофронтенди для створення складних банківських додатків, таких як портали онлайн-банкінгу, інвестиційні платформи та торгові системи. Глобальний банк може мати команди в різних країнах, які розробляють мікрофронтенди для різних регіонів, кожен з яких адаптований до місцевих нормативних актів та уподобань клієнтів.
- Системи управління контентом (CMS): Платформи CMS можуть використовувати мікрофронтенди, щоб дозволити користувачам налаштовувати зовнішній вигляд та функціональність своїх веб-сайтів. Наприклад, канадська компанія, що надає послуги CMS, може дозволити користувачам додавати або видаляти різні мікрофронтенди (віджети) на свій веб-сайт для налаштування його функціональності.
- Панелі моніторингу та аналітичні платформи: Мікрофронтенди добре підходять для створення панелей моніторингу та аналітичних платформ, де різні команди можуть додавати різні віджети та візуалізації.
- Додатки для охорони здоров'я: Постачальники медичних послуг використовують мікрофронтенди для створення порталів для пацієнтів, систем електронних медичних карток (EHR) та платформ телемедицини.
Найкращі практики для впровадження Module Federation
Щоб забезпечити успіх вашої реалізації Module Federation, дотримуйтесь цих найкращих практик:
- Ретельно плануйте: Перш ніж почати, ретельно сплануйте архітектуру мікрофронтендів та визначте чіткі межі між різними додатками.
- Створюйте чіткі канали комунікації: Створюйте чіткі канали комунікації між командами, відповідальними за різні мікрофронтенди.
- Автоматизуйте розгортання: Автоматизуйте процес розгортання, щоб забезпечити швидке та надійне розгортання мікрофронтендів.
- Моніторте продуктивність: Відстежуйте продуктивність вашої архітектури мікрофронтендів для виявлення та усунення вузьких місць.
- Впроваджуйте надійну обробку помилок: Впроваджуйте надійну обробку помилок, щоб запобігти каскадним збоям та забезпечити стійкість додатка.
- Використовуйте єдиний стиль коду: Забезпечуйте дотримання єдиного стилю коду в усіх мікрофронтендах для покращення підтримуваності.
- Документуйте все: Документуйте свою архітектуру, залежності та протоколи комунікації, щоб система була добре зрозумілою та підтримуваною.
- Враховуйте наслідки для безпеки: Ретельно враховуйте наслідки для безпеки вашої архітектури мікрофронтендів та впроваджуйте відповідні заходи безпеки. Забезпечте дотримання глобальних правил конфіденційності даних, таких як GDPR та CCPA.
Висновок
JavaScript Module Federation у Webpack 5 надає потужний та гнучкий спосіб створення архітектур мікрофронтендів. Розбиваючи великі додатки на менші, незалежно розгортані частини, ви можете покращити масштабованість, підтримуваність та автономію команд. Хоча існують виклики, пов'язані з впровадженням мікрофронтендів, переваги часто переважують витрати, особливо для складних веб-додатків. Дотримуючись найкращих практик, викладених у цьому посібнику, ви зможете успішно використовувати Module Federation для створення надійних та масштабованих архітектур мікрофронтендів, які відповідають потребам вашої організації та користувачів у всьому світі.