Module Federation в Webpack 5, плагин для обмена модулями между Javascript приложениями, описание и пример

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

В пятой версии сборщика Webpack появился набор плагинов для обмена модулями между Javascript приложениями.

Эта статья — краткое описание и пример на основе двух небольших приложений построенных на фреймворке ReactJS.

Плагин Module Federation позволяет приложению экспортировать один или несколько модулей в отдельный JS файл. Отличный способ строить микрофронтенд приложения. Сторонние приложения могут импортировать себе готовые модули, это могут быть например реакт компоненты. Причём, импорт зависимостей Webpack берёт на себя. Отличие от NPM в том, что импорт в runtime.



Приложение-источник в конфиге webpack явно указывает:

  • модули для экспорта
  • имя файла экспорта например export.js
  • зависимости, которые экспортировать не нужно например export.js

В HTML приложения-получателя импортируется JS файл приложения-источника как обычный JS скрипт:

<script src="http://source-app.com/export.js"> 

А в webpack конфиге, указывается какие модули брать из файла.

Вот как это выглядит


Приложение-источник должно прописать экспорт в настройках webpack.config.js
В настройках плагина указываем название экспортируемого контейнера, какие модули в него войдут и как будет называться файл.

пример конфига
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
 
module.exports = {
 ...
 plugins: [
   new ModuleFederationPlugin({
     name: 'home',
     library: { type: 'var', name: 'home' },
     filename: 'export.js',
     exposes: {
       ProductCarousel: './src/ProductCarousel'
     },
     shared: ['react', 'react-dom', '@material-ui/core', '@material-ui/icons']
   }),
 ]
};

Приложение-получатель

  • В index.html импортирует js файл приложения-источника

    пример
    <!DOCTYPE html>
    <html lang="en">
     <head>
       <script src="http://source-app.com/export.js"></script>

  • В webpack.config.js, в настройках плагина указываем название нужного контейнера, плагин сам найдёт его в JS файле

    пример конфига
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
     
    module.exports = {
    ...
     plugins: [
       new ModuleFederationPlugin({
         remotes: {home: 'home' } //указываем контейнер
       }),
     ]
    };

  • В JSX импортируем модуль из нужного контейнера, как будто это обычный локальный модуль

    пример кода
    import React from 'react';
    import ProductCarousel from 'home/ProductCarousel';
     
    function App() {
     return (
         <ProductCarousel />
     );
    }
     
    export default App;


Вот более подробный пример со ссылкой на репозиторий


  1. Склонируйте репо github.com/jherr/wp5-intro-video-code
  2. Установите зависимости и запустите проект

    yarn install
    yarn start
  3. Запустятся три простых реакт приложения на разных портах
    home (packages/home) localhost:3001/
    search page (packages/search) localhost:3002/
    nav (packages/nav) localhost:3003/

  4. Обратите внимание на вебпак в home: packages/home/webpack.config.js, там уже настроен экспорт компонента ProductCarousel

    new ModuleFederationPlugin({
         name: 'home',
         library: { type: 'var', name: 'home' },
         filename: 'remoteEntry.js', //в этом файле будет весь экспорт приложения для внешних получателей
         remotes: {
           nav: 'nav'
         },
         exposes: {
           ProductCarousel: './src/ProductCarousel'  //экспортируем один модуль, назовём его ProductCarousel
         },
         shared: ['react', 'react-dom', '@material-ui/core', '@material-ui/icons'] //это должно быть у получателя
       }),

    Вот как выглядит этот компонент в приложении home (я обвёл его красной рамкой)


  5. Теперь импортируем этот компонент в приложении SearchPage

    1. В packages/search/public/index.html добавьте импорт JS файла который экспортирует home, он называется remoteEntry.js (обратите внимание на порт 3001 — это порт приложения home)

      <!DOCTYPE html>
      <html lang="en">
       <head>
         <script src="http://localhost:3003/remoteEntry.js"></script>
         <script src="http://localhost:3001/remoteEntry.js"></script>
       </head>
       <body>
         <div id="root"></div>
       </body>
      </html>
    2. В настройках вебпак опишите контейнер который мы импортируем. Для этого в remotes просто добавьте название контейнера который вы импортируете, ModuleFederation сам найдёт его. (На самом деле для импорта никакие другие настройки плагина для импорта не нужны, вы можете удалить все настройки кроме remotes и импорт останется рабочим)

      module.exports = {
       ...
       plugins: [
         new ModuleFederationPlugin({
           name: 'search',
           library: { type: 'var', name: 'search' },
           filename: 'remoteEntry.js',
           remotes: {
             nav: 'nav',
             home: 'home'
           },
           exposes: {
           },
           shared: ['react', 'react-dom', '@material-ui/core', '@material-ui/icons']
         }),
    3. Теперь просто втавьте этот компонент в коде SearchPage, packages/search/src/App.jsx

      import ProductCarousel from 'home/ProductCarousel';
      function App() {
       return (
         <Container fixed>
           <CssBaseline />
           <Header />
           <Typography variant="h3">
             Search Page.
           </Typography>
           <ProductCarousel />
         </Container>
       );
      }

  6. Остановите скрипт yarn и запустите заново, что бы изменения вебпак вступили в силу. Откройте приложение SearchPage и обратите внимание что там появилась карусель из приложения home localhost:3002/
    Было Стало

Полезные ссылки


  • Официальное описание вебпак плагина здесь webpack.js.org/concepts/module-federation
  • Статья с примером indepth.dev/webpack-5-module-federation-a-game-changer-in-javascript-architecture
  • Отличное видео с объяснением и примером кода youtu.be/D3XYAx30CNc
Источник: https://habr.com/ru/post/506634/

Интересные статьи

Интересные статьи

Последние несколько недель я работал над своим сайтом и хотел придать ему некоторый динамизм. Эта статья не о создании веб-страницы. Я покажу готовые сниппеты с объяснениями. ...
Я — большой любитель TypeScript. По возможности я стараюсь использовать этот язык в своих проектах. TypeScript даёт разработчику отчёты об ошибках и проверку типов в JavaScript и TypeScript-коде....
Disclaimer. Костис Капелонис — Developer advocate (человек, защищающий и отстаивающий принципы программной разработки) Codefresh, первой платформы CI/CD для Kubernetes и контейнеров. Миссия Codef...
Как быстро определить, что на отдельно взятый сайт забили, и им никто не занимается? Если в подвале главной страницы в копирайте стоит не текущий год, а старый, то именно в этом году опека над са...
* скорее всего, я что-нибудь да упустил, но уверен, в комментариях мне это подскажут Эту статью я пишу для своих личных нужд. Планируется, что она будет содержать в себе ответы на все вопросы,...