Содержание статьи

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

  2. Проблема монолитного приложения

  3. На что стоит обращать внимание при выборе архитектуры?

  4. Примеры архитектурных решений

  5. В каких ситуациях стоит использовать Module Federation?

  6. Проблемы

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

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

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

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

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

Полезная ссылка с подробным объяснением концепции микрофронтенда.

Проблема монолитного приложения

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

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

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

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

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

На что стоит обращать внимание при выборе архитектуры?

Выбор конкретного варианта реализации микрофронтенд-архитектуры зависит от многих факторов, включая размер и сложность проекта, технологические требования, уровень опыта команды разработчиков и другие факторы. Нет одного "лучшего" варианта реализации - каждый инструмент имеет свои сильные и слабые стороны, и выбор инструмента зависит от конкретных потребностей проекта.

Вот несколько факторов, которые могут повлиять на выбор инструмента для реализации микрофронтенд-архитектуры:

  1. Границы между микрофронтендами. Определение границ между микрофронтендами - это один из самых важных этапов проектирования архитектуры микрофронтенда. Необходимо определить, какие компоненты приложения будут вынесены в отдельные микрофронтенды, а какие будут оставлены в основном приложении. Необходимо найти баланс между слишком маленькими и слишком большими микрофронтендами.

  2. Коммуникация между микрофронтендами. Каким образом микрофронтенды будут общаться между собой - это тоже важный вопрос. Необходимо определить, какие протоколы будут использоваться для коммуникации, какая будет структура сообщений и как они будут обрабатываться.

  3. Архитектурный паттерн. Существует несколько архитектурных паттернов для микрофронтенда, например, паттерн модульной федерации и паттерн comand bus. Каждый из них имеет свои достоинства и недостатки, поэтому необходимо выбрать паттерн, который лучше всего подходит для вашего приложения.

  4. Инструменты и технологии. Для реализации микрофронтенда требуются специальные инструменты и технологии, такие как библиотеки для динамической загрузки модулей, системы управления состоянием и т.д. Необходимо выбрать технологии, которые наилучшим образом соответствуют вашим потребностям.

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

  6. Совместимость и безопасность. При выборе архитектуры микрофронтенда необходимо обратить внимание на совместимость и безопасность системы.

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

  8. Управление состоянием. Управление состоянием - это одна из важных частей архитектуры микрофронтенда. Необходимо определить, как состояние будет управляться между различными микрофронтендами и какие инструменты будут использоваться для управления состоянием.

  9. Удобство разработки. Необходимо обратить внимание на удобство разработки микрофронтенда. Разработка микрофронтенда должна быть удобной и интуитивно понятной для разработчиков, чтобы облегчить разработку и поддержку приложения в будущем.

  10. Надежность и отказоустойчивость. Наконец, при выборе архитектуры микрофронтенда необходимо обратить внимание на надежность и отказоустойчивость системы.

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

Примеры архитектурных решений

1. Webpack Module Federation

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

Пример кода для создания микрофронтенда с использованием Webpack Module Federation:

// webpack.config.js

const { ModuleFederationPlugin } = require('webpack').container;

module.exports = {
  // ...
  plugins: [
    new ModuleFederationPlugin({
      name: 'my_microfrontend',
      library: { type: 'var', name: 'my_microfrontend' },
      filename: 'remoteEntry.js',
      exposes: {
        './Button': './src/Button',
      },
    }),
  ],
};
// Button.js

const Button = ({ text, onClick }) => {
  return (
    <button onClick={onClick}>
      {text}
    </button>
  );
};

export default Button;

Достаточно подробно про Module Federation я рассказал в своей статье.

2. Single-SPA

Single-SPA - это инструмент для создания микрофронтендов с использованием JavaScript-фреймворков (например, React, Vue, Angular). Он позволяет создавать отдельные фронтенд-приложения и объединять их вместе в одно приложение на стороне клиента, используя маршрутизацию.

Пример кода для создания микрофронтенда с использованием Single-SPA:

// src/Button.js

import React from 'react';

const Button = ({ text, onClick }) => {
  return (
    <button onClick={onClick}>
      {text}
    </button>
  );
};

export default Button;
// src/ButtonApp.js

import React from 'react';
import ReactDOM from 'react-dom';
import singleSpaReact from 'single-spa-react';
import Button from './Button';

const ButtonApp = () => {
  return (
    <Button text="Click me" onClick={() => alert('Button clicked!')} />
  );
};

const ButtonAppWrapper = singleSpaReact({
  React,
  ReactDOM,
  rootComponent: ButtonApp,
});

export { ButtonAppWrapper };

Полезная ссылка на документацию по single-spa

3. Podium

Podium - это инструмент для создания микрофронтендов с использованием JavaScript-фреймворков (например, React, Vue, Angular). Он позволяет создавать отдельные фронтенд-приложения и объединять их вместе в одно приложение на стороне сервера, используя шаблоны.

Пример кода для создания микрофронтенда с использованием Podium:

// src/Button.js

import React from 'react';

const Button = ({ text, onClick }) => {
  return (
    <button onClick={onClick}>
      {text}
    </button>
  );
};

export default Button;
// src/ButtonApp.js

import Podium from '@podium/client';
import Button from './Button';

const podium = new Podium();

const ButtonApp = {
  name: 'button_app',
  assets: {
    js: ['http://localhost:3000/remoteEntry.js'],
  },
  template: ({ render }) => {
    const content = render('button', { text: 'Click me' });
    return `
      <html>
        <head>
          <title>Button App</title>
        </head>
        <body>
          ${content}
        </body>
      </html>
    `;
  },
};

podium.register(ButtonApp);

podium.mount('button', ({ text }) => {
  return <Button text={text} onClick={() => alert('Button clicked!')} />;
});

export default ButtonApp;

Полезная ссылка на документацию Podium

4. Open Components

Open Components - это инструмент для создания микрофронтендов с использованием любых технологий, включая HTML, CSS, JavaScript и Web Components. Он позволяет создавать отдельные фронтенд-приложения и объединять их вместе в одно приложение на стороне сервера, используя шаблоны.

Пример кода для создания микрофронтенда с использованием Open Components:

<!-- src/Button.html -->

<button>{{text}}</button>
// src/ButtonApp.js

import OpenComponents from 'oc-client';
import Button from './Button.html';

const oc = new OpenComponents();

const ButtonApp = oc.create('button_app', ({ props }) => {
  return Button(props);
});

oc.register(ButtonApp);

export default ButtonApp;

Полезная ссылка на документацию Open Components

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

В каких ситуациях стоит использовать Module Federation

Давайте рассмотрим несколько причин, при которых Module Federation:

  1. Многомодульные приложения. Если у вас есть крупное многомодульное приложение, то MF может помочь вам разделить код между разными модулями и упростить поддержку и разработку приложения.

  2. Распределенная разработка. Если ваша команда разработки распределена по разным местам, MF может помочь вам снизить связность между разными микросервисами и упростить их интеграцию.

  3. Переиспользование кода. MF может помочь вам переиспользовать код и функциональность между разными приложениями и микросервисами, что может сократить время разработки и улучшить качество кода.

  4. Гибкость и масштабируемость. MF может помочь вам создать более гибкую и масштабируемую архитектуру, позволяя вам быстро добавлять и удалять приложения и микросервисы, не нарушая целостность системы.

  5. Ускорение разработки. Модульная федерация может помочь вам ускорить разработку, позволяя разным командам работать независимо друг от друга и интегрировать свой код с помощью модульной федерации.

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

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

Проблемы

У микрофронтендов есть некоторые проблемы, которые могут возникать при их использовании:

  1. Сложность интеграции: при использовании микрофронтендов необходимо реализовать механизмы для интеграции различных частей приложения в единую систему. Это может привести к сложностям при интеграции существующих и новых компонентов.

  2. Управление состоянием: при использовании микрофронтендов возникает необходимость в управлении состоянием между различными компонентами приложения. Это может привести к сложностям в отслеживании состояния и синхронизации данных между различными компонентами.

  3. Сложность тестирования: при использовании микрофронтендов возникает необходимость в тестировании отдельных компонентов и их интеграции. Это может привести к сложностям в настройке окружения тестирования и в написании тестов для различных компонентов.

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

  5. Увеличение сложности кода: при использовании микрофронтендов возможно увеличение сложности кода приложения из-за необходимости реализации механизмов интеграции и управления состоянием.

Несмотря на все эти потенциальные проблемы, плюсы, которые есть у микрофронтовой архитектуры, перевешивают все недостатки.

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

Комментарии (21)


  1. DreamShaded
    00.00.0000 00:00
    +7

    Ещё одной важной проблемой микрофронтов является производительность. Бьёт оч сильно по ряду метрик ж


    1. BoumRZ Автор
      00.00.0000 00:00
      +1

      А можете подробнее объяснить насчет проблемы с метриками?


      1. dagot32167
        00.00.0000 00:00
        +1

        у нас микрофронтовость может быть реализована несколькими вариантами:
        - билдтайм
        - рантайм
        - SSI

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

        Если мы говорим про рантайм (например module federation) то появляется лишняя асинхронность, которая может повлиять на web vitals, ведь ты не можешь гарантировать скорость ответа за новым чанком с JS который повлияет на рендер
        Если мы говорим про рантайм и SSI ты не контролируешь, что другая команда вставила в свой микрофронт, а значит твой перформанс больше не твой, а общий. Они могут обмазаться библиотеками, сложными вычислениями и прочим, ты это не контролируешь. Так же обвязка, которая позволяет сделать модули, асинхронными не является "бесплатной". Хотя иногда можно подумать, что это экономия на спичках.

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


      1. dagot32167
        00.00.0000 00:00
        +2

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


      1. dagot32167
        00.00.0000 00:00
        +3

        Еще забыл. за частую микрофронты — это забыть про дедупликацию. Module federation может это делать, но с учетом, что все добросовестно указали свои зависимости. Но также из-за этого treeshaking не допустим, т. к. ты не знаешь, какой кусок этой либы нужен в другом микрофронте.


        1. DreamShaded
          00.00.0000 00:00

          о, благодарю, я чёт пропустил вопрос) да, всё по делу, это в общем-то часто обсуждается что тут, что на ивентах. Хотелось бы в статье решений новых)


    1. cannibal_corpse
      00.00.0000 00:00
      +1

      Роман, ну что вы сразу на грабли.
      Можно же оптимизировать =)
      Не написал в этой статье - напишет в следующей по просьбам желающих


      1. DreamShaded
        00.00.0000 00:00

        Ооо, привет!) Рад тебе)

        По вопросу: так я и не против, плюсанул автору и в карму, и в пост, но вопрос такой, больной, плюсы и минусы без перформанса странно. Хотя щас каждый третий сайт жрёт безмерно, мб модно не париться о производительности


  1. Mihaelc
    00.00.0000 00:00
    +2

    А как происходит общение двух микрофронтендов, например, на React и Angular, если откинуть вариант гнать сообщения через бэкенд?


    1. BoumRZ Автор
      00.00.0000 00:00

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


    1. dagot32167
      00.00.0000 00:00
      +1

      если планируется использовать разные фреймворки\технологии работы с фронтом, то проще использовать подход eventbus и общаться сообщениями через какой-то общедоступный узел (хоть body). Это даст тебе слабосвязанность и фреймворк агностность (хз есть такое слово или нет))).
      Но при этом я бы (да и всех, кого знаю) не советовал на одном продукте использовать разные фреймворки. Производительность такого приложения пойдет ко дну


  1. StiPAFk
    00.00.0000 00:00

    Основная проблема как по мне не подсвечена. а как же изолирование приложений? если у вас допустим есть приложение главной страницы которое ресетит стили и есть часть другого приложения которому ресет стилей не нужен? тоже самое касается кода.

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


    1. BoumRZ Автор
      00.00.0000 00:00

      Ресет стилей можно сделать точно также, как если бы ресет происходил в рамках одного приложения. Разбиение на микрофронты не влияет на решение


      1. StiPAFk
        00.00.0000 00:00

        ну как же не влияет - первое приложение требует ресета стилей второе нет. вся суть проблемы что если одно приложение использует другое то они оба получат эти стили. в чанке обоих это будет существовать. и номральной изоляции кроме как вебкмпонентов и iframe в данный момент не существует)


        1. BoumRZ Автор
          00.00.0000 00:00

          Ну тут проблема не микрофронтами, это то же самое, если один кусок одного приложения требует ресета, а в другой кусок этого же приложения - нет


          1. StiPAFk
            00.00.0000 00:00
            +1

            так обе части приложение пишутся в одном окружении - а в случае микрофронтов ты не знаешь куда встраивается твоё приложение по этой причине они должны быть изолированы


            1. AVSDoom
              00.00.0000 00:00

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


  1. dagot32167
    00.00.0000 00:00
    +4

    Со своей стороны могу сказать, что немного не согласен, что микрофронтовая архитектура лучше монолитной. Тут, как и в любом архитектурном решении "it depends". Каждый случай надо рассматривать индивидуально. Зависит от компании и ее организации (часто организация определяет архитектуру проектов), от самого проекта и требований по нему.
    За частую, хорошо структурированный код в монолите будет лучше, чем множество отдельных частей сайта, разбросанных по отдельным "микрофронтам". Качественнее и проще тестируемость. Меньше бандл. Проще контроль за кешами. Ресурсов монолиты жрут меньше (если в целом посмотреть).
    Микрофронты дают гибкость при росте команд. Когда есть четкое разделение зон ответственности (иначе канибализация и постоянны терки между командами). Быстрее time to market за счет снижения области тестирования. Проще интегрировать новых людей т.к. в меньшее кол-во кода и зону ответственности их надо погружать.


    1. Vendettarasha
      00.00.0000 00:00

      Работал я одно время в большой компании с кучей команд и с большими проектами с Single-SPA, и согласен со многими нюансами. Сейчас в новой компании у нас есть маленькая команда и большой монолит и тут стали подумывать о микрофронтенде но я пока отговариваю так как в нашем случае это мне кажется это трата сил и времени. В крайнем случае думал разбить монолит например на страницы и вынести в отдельные репы и подлючать через react-lazy, ну и они будут использовать общий стор и нашу библиотеку ui. Как вы думаете это жизнеспособный вариант разделение монолита для улучшения производительности и возможно для переиспользования этих частей монолита в других проектах?


      1. StiPAFk
        00.00.0000 00:00

        зависит от того как будут чанки собираться и на чём всё это будет работать. В целом решение вполне рабочее.


      1. dagot32167
        00.00.0000 00:00
        +2

        извини, но вообще ничего не скажу, чтобы не сказать глупости т.к. не знаю вашу текущую архитектуру, текущие проблемы поставки\разработки\поддержки, где именно узкое горлышко перформанс (и какие именно метрики туда вкладываются), кто ваш клиент (и его технические ограничения), а самое главное "разделить монолит что бы что?" (блин, Дорофеев покусал). Т.е. что именно хочется решить этим рефакторингом архитектуры. Ведь это может потянуть за собой переделку тестов, пайплайнов...
        Я бы предложил первым делом понять ограничения проекта, с чем они связаны и как это аффектит на вашего пользователя. Вдруг вы смотрите на перформанс по 99 перцентилю и пытаетесь его решить, а там проблема при попадании на холодный кеш.
        При разбивании так же я бы приложил учитывать, что это за тип приложения (какой нить бекофис или клиентское приложение) т.к. в какой-то момент есть шанс того, что пользователь через все эти react-lazy так или иначе выкачает себе полностью все. Но при этом обвязки в виде асинхронности не бесплатны.