Русский

Раскройте мощь микрофронтендов с помощью JavaScript Module Federation в Webpack 5. Научитесь создавать масштабируемые, поддерживаемые и независимые веб-приложения.

JavaScript Module Federation с Webpack 5: Полное руководство по микрофронтендам

В постоянно меняющемся мире веб-разработки создание больших и сложных приложений может стать непростой задачей. Традиционные монолитные архитектуры часто приводят к увеличению времени разработки, проблемам с развертыванием и трудностям в поддержании качества кода. Микрофронтенды стали мощным архитектурным паттерном для решения этих проблем, позволяя командам создавать и развертывать независимые части большого веб-приложения. Одной из самых многообещающих технологий для реализации микрофронтендов является JavaScript Module Federation, представленная в Webpack 5.

Что такое микрофронтенды?

Микрофронтенды — это архитектурный стиль, при котором фронтенд-приложение разбивается на более мелкие, независимые блоки, которые могут разрабатываться, тестироваться и развертываться автономно разными командами. Каждый микрофронтенд отвечает за определенную бизнес-область или функцию, и они собираются вместе во время выполнения, чтобы сформировать полный пользовательский интерфейс.

Представьте себе компанию: вместо одной гигантской команды разработчиков у вас есть несколько небольших команд, сосредоточенных на конкретных областях. Каждая команда может работать независимо, что обеспечивает более быстрые циклы разработки и упрощает обслуживание. Возьмем, к примеру, крупную платформу электронной коммерции, такую как Amazon; разные команды могут управлять каталогом товаров, корзиной покупок, процессом оформления заказа и управлением учетными записями пользователей. Все это могут быть независимые микрофронтенды.

Преимущества микрофронтендов:

Проблемы микрофронтендов:

Что такое JavaScript Module Federation?

JavaScript Module Federation — это функция Webpack 5, которая позволяет совместно использовать код между отдельно скомпилированными JavaScript-приложениями во время выполнения. Она позволяет предоставлять части вашего приложения в виде «модулей», которые могут использоваться другими приложениями без необходимости публикации в центральном репозитории, таком как npm.

Думайте о Module Federation как о способе создания федеративной экосистемы приложений, где каждое приложение может предоставлять свою собственную функциональность и использовать функциональность других приложений. Это устраняет необходимость в зависимостях на этапе сборки и обеспечивает по-настоящему независимое развертывание.

Например, команда, отвечающая за дизайн-систему, может предоставлять UI-компоненты в виде модулей, а различные команды приложений могут использовать эти компоненты непосредственно из приложения дизайн-системы, без необходимости устанавливать их как npm-пакеты. Когда команда дизайн-системы обновляет компоненты, изменения автоматически отражаются во всех использующих их приложениях.

Ключевые концепции Module Federation:

Настройка 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)

В каталоге `remote` создайте следующие файлы:

src/index.js:

```javascript import React from 'react'; import ReactDOM from 'react-dom/client'; import RemoteComponent from './RemoteComponent'; const App = () => (

Remote Application

); const root = ReactDOM.createRoot(document.getElementById('root')); root.render(); ```

src/RemoteComponent.jsx:

```javascript import React from 'react'; const RemoteComponent = () => (

This is a Remote Component!

Rendered from the Remote Application.

); export default 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)

В каталоге `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 = () => (

Host Application

Loading Remote Component...
}>
); const root = ReactDOM.createRoot(document.getElementById('root')); root.render(); ```

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`. Вы должны увидеть хост-приложение с отображенным внутри него удаленным компонентом.

Объяснение ключевых опций конфигурации:

Продвинутые техники 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'); // Assume remoteUrl is something like 'http://localhost:3001/remoteEntry.js' const script = document.createElement('script'); script.src = remoteUrl; script.onload = () => { // the key of module federation is that the remote app is // available using the name in the remote resolve(window.remote); }; document.head.appendChild(script); })`, }, ```

Теперь вы можете загрузить хост-приложение с параметром запроса `?remote=http://localhost:3001/remoteEntry.js`

Версионирование общих модулей (Shared Modules)

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' }, }, ```

Пользовательские загрузчики модулей

Module Federation позволяет определять пользовательские загрузчики модулей, которые могут использоваться для загрузки модулей из разных источников или в разных форматах. Это может быть полезно для загрузки модулей с CDN или из пользовательского реестра модулей.

Обмен состоянием между микрофронтендами

Одной из проблем архитектуры микрофронтендов является обмен состоянием между различными микрофронтендами. Существует несколько подходов, которые вы можете использовать для решения этой проблемы:

Лучшие практики для внедрения микрофронтендов с Module Federation

Вот несколько лучших практик, которые следует учитывать при внедрении микрофронтендов с Module Federation:

Реальные примеры использования Module Federation

Хотя конкретные кейсы часто являются конфиденциальными, вот несколько обобщенных сценариев, где Module Federation может быть невероятно полезен:

Заключение

JavaScript Module Federation в Webpack 5 предоставляет мощный и гибкий способ создания архитектур микрофронтендов. Он позволяет совместно использовать код между отдельно скомпилированными JavaScript-приложениями во время выполнения, обеспечивая независимое развертывание, технологическое разнообразие и повышенную автономию команд. Следуя лучшим практикам, изложенным в этом руководстве, вы можете использовать Module Federation для создания масштабируемых, поддерживаемых и инновационных веб-приложений.

Будущее фронтенд-разработки, несомненно, движется в сторону модульных и распределенных архитектур. Module Federation предоставляет важнейший инструмент для создания этих современных систем, позволяя командам создавать сложные приложения с большей скоростью, гибкостью и отказоустойчивостью. По мере развития технологии можно ожидать появления еще более инновационных сценариев использования и лучших практик.