Отключете силата на микро-фронтендите с JavaScript Module Federation в Webpack 5. Научете как да изграждате мащабируеми, лесни за поддръжка и независими уеб приложения.
JavaScript Module Federation с Webpack 5: Цялостно ръководство за микро-фронтенди
В постоянно развиващия се свят на уеб разработката, изграждането на големи и сложни приложения може да бъде обезсърчаваща задача. Традиционните монолитни архитектури често водят до увеличено време за разработка, затруднения при внедряване и предизвикателства в поддържането на качеството на кода. Микро-фронтендите се появиха като мощен архитектурен модел за справяне с тези предизвикателства, позволявайки на екипите да изграждат и внедряват независими части от по-голямо уеб приложение. Една от най-обещаващите технологии за прилагане на микро-фронтенди е JavaScript Module Federation, въведена в Webpack 5.
Какво са микро-фронтенди?
Микро-фронтендите са архитектурен стил, при който фронтенд приложението се разгражда на по-малки, независими единици, които могат да бъдат разработвани, тествани и внедрявани автономно от различни екипи. Всеки микро-фронтенд отговаря за конкретна бизнес област или функционалност, и те се сглобяват заедно по време на изпълнение, за да формират цялостния потребителски интерфейс.
Представете си го като компания: вместо да имате един огромен екип за разработка, имате няколко по-малки екипа, фокусирани върху конкретни области. Всеки екип може да работи независимо, което позволява по-бързи цикли на разработка и по-лесна поддръжка. Да вземем за пример голяма платформа за електронна търговия като Amazon; различни екипи може да управляват продуктовия каталог, пазарската количка, процеса на плащане и управлението на потребителски акаунти. Всички те биха могли да бъдат независими микро-фронтенди.
Предимства на микро-фронтендите:
- Независими внедрявания: Екипите могат да внедряват своите микро-фронтенди независимо, без да засягат други части на приложението. Това намалява риска при внедряване и позволява по-бързи цикли на издаване.
- Технологична независимост: Различни микро-фронтенди могат да бъдат изградени с помощта на различни технологии или рамки (напр. React, Angular, Vue.js). Това позволява на екипите да изберат най-добрата технология за своите специфични нужди и постепенно да възприемат нови технологии, без да се налага да пренаписват цялото приложение. Представете си един екип, използващ React за продуктовия каталог, друг, използващ Vue.js за маркетингови целеви страници, и трети, използващ Angular за процеса на плащане.
- Подобрена автономност на екипа: Екипите имат пълна собственост върху своите микро-фронтенди, което води до увеличена автономност, по-бързо вземане на решения и подобрена производителност на разработчиците.
- Повишена мащабируемост: Микро-фронтендите ви позволяват да мащабирате приложението си хоризонтално, като внедрявате отделни микро-фронтенди на различни сървъри.
- Повторно използване на код: Споделените компоненти и библиотеки могат лесно да се споделят между микро-фронтенди.
- По-лесна поддръжка: По-малките кодови бази обикновено са по-лесни за разбиране, поддръжка и отстраняване на грешки.
Предизвикателства на микро-фронтендите:
- Повишена сложност: Управлението на множество микро-фронтенди може да добави сложност към цялостната архитектура, особено по отношение на комуникация, управление на състоянието и внедряване.
- Натоварване на производителността: Зареждането на множество микро-фронтенди може да доведе до натоварване на производителността, особено ако не са оптимизирани правилно.
- Общи аспекти (Cross-Cutting Concerns): Справянето с общи аспекти като удостоверяване, оторизация и теми може да бъде предизвикателство в микро-фронтенд архитектура.
- Оперативни разходи: Изисква зрели DevOps практики и инфраструктура за управление на внедряването и наблюдението на множество микро-фронтенди.
Какво е JavaScript Module Federation?
JavaScript Module Federation е функция на Webpack 5, която ви позволява да споделяте код между отделно компилирани JavaScript приложения по време на изпълнение. Тя ви дава възможност да излагате части от вашето приложение като "модули", които могат да бъдат консумирани от други приложения, без да е необходимо да ги публикувате в централно хранилище като npm.
Мислете за Module Federation като за начин да създадете федеративна екосистема от приложения, където всяко приложение може да допринася със собствена функционалност и да консумира функционалност от други приложения. Това елиминира нуждата от зависимости по време на компилация (build-time) и позволява наистина независими внедрявания.
Например, екипът по дизайн система може да изложи UI компоненти като модули, а различни екипи на приложения могат да консумират тези компоненти директно от приложението на дизайн системата, без да е необходимо да ги инсталират като npm пакети. Когато екипът на дизайн системата актуализира компонентите, промените автоматично се отразяват във всички консумиращи приложения.
Ключови концепции в Module Federation:
- Host (Хост): Основното приложение, което консумира отдалечени модули.
- Remote (Отдалечен): Приложение, което излага модули, за да бъдат консумирани от други приложения.
- Shared Modules (Споделени модули): Модули, които се споделят между хост и отдалечени приложения (напр. React, Lodash). Module Federation може автоматично да управлява версиите и дедупликацията на споделените модули, за да гарантира, че се зарежда само една версия на всеки модул.
- Exposed Modules (Изложени модули): Специфични модули от отдалечено приложение, които са предоставени за консумация от други приложения.
- RemoteEntry.js: Файл, генериран от Webpack, който съдържа метаданни за изложените модули на отдалеченото приложение. Хост приложението използва този файл, за да открие и зареди отдалечените модули.
Настройка на Module Federation с Webpack 5: Практическо ръководство
Нека разгледаме практически пример за настройка на Module Federation с Webpack 5. Ще създадем две прости приложения: Host (хост) приложение и Remote (отдалечено) приложение. Отдалеченото приложение ще изложи компонент, а хост приложението ще го консумира.
1. Настройка на проекта
Създайте две отделни директории за вашите приложения: `host` и `remote`.
```bash mkdir host remote cd host npm init -y npm install webpack webpack-cli webpack-dev-server html-webpack-plugin --save-dev npm install react react-dom cd ../remote npm init -y npm install webpack webpack-cli webpack-dev-server html-webpack-plugin --save-dev npm install react react-dom ```2. Конфигурация на отдалеченото приложение
В директорията `remote` създайте следните файлове:
- `src/index.js`: Входна точка за приложението.
- `src/RemoteComponent.jsx`: Компонентът, който ще бъде изложен.
- `webpack.config.js`: Конфигурационен файл на Webpack.
src/index.js:
```javascript import React from 'react'; import ReactDOM from 'react-dom/client'; import RemoteComponent from './RemoteComponent'; const App = () => (Отдалечено приложение
src/RemoteComponent.jsx:
```javascript import React from 'react'; const RemoteComponent = () => (Това е отдалечен компонент!
Рендиран от отдалеченото приложение.
webpack.config.js:
```javascript const HtmlWebpackPlugin = require('html-webpack-plugin'); const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin'); const path = require('path'); module.exports = { entry: './src/index', mode: 'development', devServer: { port: 3001, static: { directory: path.join(__dirname, 'dist'), }, }, output: { publicPath: 'auto', }, module: { rules: [ { test: /\.(js|jsx)$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-react', '@babel/preset-env'], }, }, }, ], }, plugins: [ new ModuleFederationPlugin({ name: 'remote', filename: 'remoteEntry.js', exposes: { './RemoteComponent': './src/RemoteComponent', }, shared: { react: { singleton: true, eager: true }, 'react-dom': { singleton: true, eager: true }, }, }), new HtmlWebpackPlugin({ template: './public/index.html', }), ], resolve: { extensions: ['.js', '.jsx'], }, }; ```Създайте `public/index.html` с основна HTML структура. Важен е елементът `
`3. Конфигурация на хост приложението
В директорията `host` създайте следните файлове:
- `src/index.js`: Входна точка за приложението.
- `webpack.config.js`: Конфигурационен файл на Webpack.
src/index.js:
```javascript import React, { Suspense } from 'react'; import ReactDOM from 'react-dom/client'; const RemoteComponent = React.lazy(() => import('remote/RemoteComponent')); const App = () => (Хост приложение
webpack.config.js:
```javascript const HtmlWebpackPlugin = require('html-webpack-plugin'); const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin'); const path = require('path'); module.exports = { entry: './src/index', mode: 'development', devServer: { port: 3000, static: { directory: path.join(__dirname, 'dist'), }, }, output: { publicPath: 'auto', }, module: { rules: [ { test: /\.(js|jsx)$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-react', '@babel/preset-env'], }, }, }, ], }, plugins: [ new ModuleFederationPlugin({ name: 'host', remotes: { remote: 'remote@http://localhost:3001/remoteEntry.js', }, shared: { react: { singleton: true, eager: true }, 'react-dom': { singleton: true, eager: true }, }, }), new HtmlWebpackPlugin({ template: './public/index.html', }), ], resolve: { extensions: ['.js', '.jsx'], }, }; ```Създайте `public/index.html` с основна HTML структура (подобно на отдалеченото приложение). Важен е елементът `
`4. Инсталиране на Babel
И в директорията `host`, и в `remote` инсталирайте зависимостите на Babel:
```bash npm install --save-dev @babel/core @babel/preset-env @babel/preset-react babel-loader ```5. Стартиране на приложенията
И в директорията `host`, и в `remote` добавете следния скрипт към `package.json`:
```json "scripts": { "start": "webpack serve" } ```Сега стартирайте и двете приложения:
```bash cd remote npm start cd ../host npm start ```Отворете браузъра си и отидете на `http://localhost:3000`. Трябва да видите хост приложението с рендиран в него отдалечен компонент.
Обяснение на ключови опции за конфигурация:
- `name`: Уникално име за приложението.
- `filename`: Името на файла, който ще съдържа метаданните за изложените модули (напр. `remoteEntry.js`).
- `exposes`: Карта на имената на модулите към пътищата на файловете, указваща кои модули трябва да бъдат изложени.
- `remotes`: Карта на имената на отдалечените приложения към URL адреси, указваща къде да се намери файлът remoteEntry.js за всяко отдалечено приложение.
- `shared`: Списък с модули, които трябва да се споделят между хост и отдалечените приложения. Опцията `singleton: true` гарантира, че се зарежда само едно копие на всеки споделен модул. Опцията `eager: true` гарантира, че споделеният модул се зарежда незабавно (т.е. преди всички други модули).
Напреднали техники с Module Federation
Module Federation предлага много разширени функции, които могат да ви помогнат да изградите още по-сложни микро-фронтенд архитектури.
Динамични Remotes
Вместо да кодирате твърдо URL адресите на отдалечените приложения в конфигурацията на Webpack, можете да ги зареждате динамично по време на изпълнение. Това ви позволява лесно да актуализирате местоположението на отдалечените приложения, без да се налага да прекомпилирате хост приложението.
Например, можете да съхранявате URL адресите на отдалечените приложения в конфигурационен файл или база данни и да ги зареждате динамично с помощта на JavaScript.
```javascript // В webpack.config.js remotes: { remote: `promise new Promise(resolve => { const urlParams = new URLSearchParams(window.location.search); const remoteUrl = urlParams.get('remote'); // Да приемем, че remoteUrl е нещо като 'http://localhost:3001/remoteEntry.js' const script = document.createElement('script'); script.src = remoteUrl; script.onload = () => { // ключът на module federation е, че отдалеченото приложение е // достъпно чрез името в remote resolve(window.remote); }; document.head.appendChild(script); })`, }, ```Сега можете да заредите хост приложението с параметър в заявката `?remote=http://localhost:3001/remoteEntry.js`
Версионирани споделени модули
Module Federation може автоматично да управлява версиите и дедупликацията на споделените модули, за да гарантира, че се зарежда само една съвместима версия на всеки модул. Това е особено важно при работа с големи и сложни приложения, които имат много зависимости.
Можете да посочите обхвата на версиите на всеки споделен модул в конфигурацията на Webpack.
```javascript // В webpack.config.js shared: { react: { singleton: true, eager: true, requiredVersion: '^18.0.0' }, 'react-dom': { singleton: true, eager: true, requiredVersion: '^18.0.0' }, }, ```Персонализирани зареждащи модули (Loaders)
Module Federation ви позволява да дефинирате персонализирани зареждащи модули, които могат да се използват за зареждане на модули от различни източници или в различни формати. Това може да бъде полезно за зареждане на модули от CDN или от персонализиран регистър на модули.
Споделяне на състояние между микро-фронтенди
Едно от предизвикателствата на микро-фронтенд архитектурите е споделянето на състояние между различните микро-фронтенди. Има няколко подхода, които можете да предприемете, за да се справите с това предизвикателство:
- Управление на състоянието чрез URL: Съхранявайте състоянието в URL адреса и го използвайте за комуникация между микро-фронтендите. Това е прост и ясен подход, но може да стане тромав при сложно състояние.
- Персонализирани събития (Custom events): Използвайте персонализирани събития за разпространение на промени в състоянието между микро-фронтендите. Това позволява слабо обвързване между микро-фронтендите, но управлението на абонаментите за събития може да бъде трудно.
- Споделена библиотека за управление на състоянието: Използвайте споделена библиотека за управление на състоянието като Redux или MobX, за да управлявате състоянието на цялото приложение. Това осигурява централизиран и последователен начин за управление на състоянието, но може да въведе зависимост от конкретна библиотека за управление на състоянието.
- Message Broker: Използвайте message broker като RabbitMQ или Kafka, за да улесните комуникацията и споделянето на състояние между микро-фронтендите. Това е по-сложно решение, но предлага висока степен на гъвкавост и мащабируемост.
Най-добри практики за внедряване на микро-фронтенди с Module Federation
Ето някои най-добри практики, които да имате предвид при внедряването на микро-фронтенди с Module Federation:
- Дефинирайте ясни граници за всеки микро-фронтенд: Всеки микро-фронтенд трябва да отговаря за конкретна бизнес област или функционалност и да има добре дефинирани интерфейси.
- Използвайте последователен технологичен стек: Въпреки че Module Federation ви позволява да използвате различни технологии за различните микро-фронтенди, обикновено е добра идея да използвате последователен технологичен стек, за да намалите сложността и да подобрите поддръжката.
- Установете ясни протоколи за комуникация: Дефинирайте ясни протоколи за комуникация за това как микро-фронтендите трябва да взаимодействат помежду си.
- Автоматизирайте процеса на внедряване: Автоматизирайте процеса на внедряване, за да гарантирате, че микро-фронтендите могат да бъдат внедрявани независимо и надеждно. Обмислете използването на CI/CD пътеки и инструменти за инфраструктура като код.
- Наблюдавайте производителността на вашите микро-фронтенди: Наблюдавайте производителността на вашите микро-фронтенди, за да идентифицирате и отстраните всякакви тесни места в производителността. Използвайте инструменти като Google Analytics, New Relic или Datadog.
- Внедрете стабилна обработка на грешки: Внедрете стабилна обработка на грешки, за да гарантирате, че вашето приложение е устойчиво на повреди.
- Приемете децентрализиран модел на управление: Дайте възможност на екипите да вземат решения за собствените си микро-фронтенди, като същевременно поддържате обща последователност и качество.
Примери от реалния свят за Module Federation в действие
Въпреки че конкретните казуси често са поверителни, ето някои обобщени сценарии, при които Module Federation може да бъде изключително полезен:
- Платформи за електронна търговия: Както споменахме по-рано, големите платформи за електронна търговия могат да използват Module Federation за изграждане на независими микро-фронтенди за продуктовия каталог, пазарската количка, процеса на плащане и управлението на потребителски акаунти. Това позволява на различни екипи да работят по тези функции независимо и да ги внедряват, без да засягат други части на приложението. Глобална платформа може да персонализира функции за различни региони чрез отдалечени модули.
- Приложения за финансови услуги: Приложенията за финансови услуги често имат сложни потребителски интерфейси с много различни функции. Module Federation може да се използва за изграждане на независими микро-фронтенди за различни видове акаунти, платформи за търговия и табла за отчитане. Функции за съответствие, уникални за определени държави, могат да бъдат доставени чрез Module Federation.
- Портали за здравеопазване: Порталите за здравеопазване могат да използват Module Federation за изграждане на независими микро-фронтенди за управление на пациенти, насрочване на прегледи и достъп до медицински досиета. Различни модули за различни застрахователни доставчици или региони могат да се зареждат динамично.
- Системи за управление на съдържанието (CMS): CMS може да използва Module Federation, за да позволи на потребителите да добавят персонализирана функционалност към своите уебсайтове чрез зареждане на отдалечени модули от разработчици на трети страни. Различни теми, плъгини и уиджети могат да се разпространяват като независими микро-фронтенди.
- Системи за управление на обучението (LMS): LMS може да предлага курсове, разработени независимо и интегрирани в единна платформа чрез Module Federation. Актуализациите на отделни курсове не изискват повторно внедряване на цялата платформа.
Заключение
JavaScript Module Federation в Webpack 5 предоставя мощен и гъвкав начин за изграждане на микро-фронтенд архитектури. Той ви позволява да споделяте код между отделно компилирани JavaScript приложения по време на изпълнение, което позволява независими внедрявания, технологично разнообразие и подобрена автономност на екипа. Като следвате най-добрите практики, очертани в това ръководство, можете да използвате Module Federation за изграждане на мащабируеми, лесни за поддръжка и иновативни уеб приложения.
Бъдещето на фронтенд разработката несъмнено клони към модулни и разпределени архитектури. Module Federation предоставя ключов инструмент за изграждането на тези модерни системи, позволявайки на екипите да създават сложни приложения с по-голяма скорост, гъвкавост и устойчивост. С узряването на технологията можем да очакваме да се появят още по-иновативни случаи на употреба и най-добри практики.