Возможности Micro Frontend
Micro Frontend - это в первую очередь не техническая вещь
С моей точки зрения, Micro Frontend - это в первую очередь не техническая вещь. Основное преимущество Micro Frontend - это возможность организовывать небольшие команды вокруг программных модулей со сквозным характером. В лучшем случае эти модули выровнены с ограниченными контекстами.
В своей статье о микросервисах Мартин Фаулер и Джеймс Льюис заявили, что существует естественная корреляция между границами сервиса и контекста. Понятие ограниченного контекста происходит от Domain Driven Design (DDD). Стратегический дизайн DDD помогает разделить систему на более мелкие, менее зависимые части в соответствии с реальным процессом. Эти части называются ограниченными контекстами, и, согласно приведенному выше утверждению, они естественным образом коррелируют с микросервисами.
Сосредоточившись на аспекте модульности, единственное различие между микросервисами и Micro Frontend состоит в том, что последний включает интерфейс. Отсутствие внешнего интерфейса затрудняет создание команд со сквозной ответственностью и часто приводит к новому монолиту во внешнем интерфейсе.
Команды со сквозной ответственностью ближе к потребностям клиентов, что позволяет им выполнять их напрямую. Микро-фронты, согласованные с ограниченным контекстом, увеличивают независимость команды. Сочетание этих двух факторов позволяет командам создавать продукты без потери производительности и ориентации на клиента в корпоративных организациях и иерархиях.
На мой взгляд, этот аспект является основным преимуществом Micro Frontends, и с учетом сказанного я перенесу акцент на техническую часть этой статьи.
Федерация Micro Frontend сегодня
Чуть более двух лет назад мы начали видеть преимущества Micro Frontends в нашем бизнес-контексте. Вначале мы играли, создавая небольшие продукты из разных Micro Frontend. Наш первый подход к интеграции заключался в использовании i-фреймов, но в нашем контексте он казался громоздким, и мы особенно поразили его границы, когда мы интегрировали несколько Micro Frontend на одной странице, где каждому требовалось получить токен доступа oauth2 с использованием активного входа в систему. сеанс (oauth2 рекомендует не разрешать загрузку страницы входа в i-frame). Конечно, были бы варианты решения этой проблемы (например, использование потока кода аутентификации oauth2 с pkce для передачи долгоживущих токенов в i-кадры), но к тому времени мы уже заметили новый стандарт веб-компонентов. , который более интуитивно решает задачу интеграции.
Вначале мы создавали веб-компоненты по-разному. Мы экспортировали компоненты Vue.js как веб-компоненты или использовали менее сложные фреймворки, такие как stencil.js или полимер. Сегодня мы в основном создаем веб-компоненты, используя световой элемент с машинописным текстом и настраиваемую конфигурацию Webpack.
В нашем реальном приложении мы уже интегрируем довольно много Micro Frontend из разных доменов. Хотя интеграция веб-компонентов является нашим предпочтительным подходом, практика научила нас быть более гибкими и позволить все, что лучше всего подходит для команд, интегрирующих свои интерфейсы.
Тот факт, что нет библиотеки пользовательского интерфейса веб-компонентов, реализующей наш фирменный стиль / дизайн, или, по крайней мере, значительного количества веб-компонентов материального дизайна, на самом деле является причиной для многих команд, которые все еще избегают веб-компонентов. Им проще использовать одностраничную структуру приложения ‹you-name-it›, для которой существует такая библиотека компонентов пользовательского интерфейса. Однако недостатком этого подхода является то, что команда теряет возможность интеграции в качестве веб-компонента. Вы пробовали интегрировать сложный компонент Vue с приложением React? Даже если вы сможете преобразовать компонент в веб-компонент, это покажется неправильным. Это то, что я имею в виду под потерей возможности интеграции в качестве веб-компонента. (Между прочим. С моей точки зрения, наиболее перспективным проектом для решения проблемы отсутствия веб-компонентов материального дизайна на данный момент является материал-компоненты-веб-компоненты)
Наше контейнерное приложение, объединяющее все эти интерфейсы, построено с использованием Vue.js, и поэтому у нас есть Micro Frontend, интегрируемые в виде библиотек компонентов Vue, i-frame, веб-компонентов и путем добавления ссылки (если такой упрощенный подход применим).
Поскольку веб-компоненты развиваются день ото дня, я думаю, что их доля будет неуклонно увеличиваться.
Сосредоточение внимания на веб-компонентах сценарий интеграции довольно интуитивно понятен, но все же существуют недостатки, которые необходимо преодолеть. Одним из важных примеров является обработка зависимостей. Представьте, что есть контейнер приложения A и веб-компонент Micro Frontend B, который будет интегрирован с A. Кроме того, существует еще один веб-компонент C, используемый A и B. Чтобы быть более конкретным, предположим, что C - это простой компонент кнопки, B - это веб-компонент, который часто загружает изображения и позволяет ставить лайки с помощью кнопки C . A может быть приложением Vue.js, которое использует C в качестве кнопки входа и интегрирует B, чтобы запрашивать у пользователей лайки об изображениях. При интеграции A с B возникают проблемы, касающиеся C. Если A и B используют одну и ту же версию C, ее следует загрузить только один раз. В связи с этим необходимо убедиться, что custom-element из C определяется только один раз. В случае использования разных версий C необходимо избегать возможных конфликтов версий. Если A перестанет использовать C, это не повлияет на B во время выполнения.
Сегодня эти проблемы можно решить с помощью внешних элементов Webpack или аналогичных подходов, которые довольно непрозрачны, особенно когда речь идет об огромных сценариях интеграции со сложными деревьями зависимостей.
К счастью, уже существуют решения для этой проблемы. Среди прочего, федерация модулей Webpack 5 является одной из них.
Федерация Micro Frontend завтра
использование интеграции модулей Webpack 5
Поскольку объединение модулей Webpack 5 является многообещающим кандидатом на устранение недостатков интеграции веб-компонентов, в этом разделе описывается, как его можно использовать на практике в сценарии простого веб-компонента.
Пример веб-компонента (удаленный)
Чтобы продемонстрировать его возможности, я реализовал простой нативный веб-компонент (без светового элемента, чтобы он был еще проще). Цель этого примера веб-компонента - загрузить новое случайное изображение с https://picsum.photos/. Частоту обновления в миллисекундах и длину квадратичного изображения можно определить с помощью custom-element:
<random-pic update-freq-ms="15000" image-length-px="300"></random-pic>
Вот как это может выглядеть:
чтобы увидеть компонент в действии, перейдите по ссылке: https://josros.gitlab.io/random-pic-component/
Цель состоит в том, чтобы предоставить компонент как удаленный модуль. « Удаленные модули - это модули, которые не являются частью текущей сборки и загружаются из так называемого контейнера во время выполнения ».
Чтобы преобразовать образец компонента в удаленный модуль, необходимо сделать следующее:
// install Webpack 5 (beta version, v.20 is used in this example) npm i [email protected] -D
Добавьте конфигурацию объединения модулей в файл webpack.config.js. Ключевая часть:
randomPic - имя модуля. Модуль предоставляет образец компонента под именем ./component, которое относится к фактической реализации веб-компонента.
Учитывая полный webpack.config.js, выполнение сборки Webpack
webpack --mode production
переносит компонент с помощью babel и создает файл randomPicEntry.js, используемый в качестве точки входа для загрузки компонента из другого места, что будет продемонстрировано в следующем разделе. (Если вы посмотрите на фактический файл webpack.config.js, просто проигнорируйте пока разделяемую часть.)
Вместе с демонстрационной страницей компонента проект примера компонента развертывает файлы, созданные с помощью Webpack, на страницах gitlab с помощью простого файла gitlab-ci.yml.
Если вас интересует способ настройки этого примера с помощью машинописного текста, посмотрите: https://gitlab.com/josros/random-pic-component-ts
Компонентная интеграция (хост)
Аналог пульта ДУ - простой проект Webpack, который интегрирует компонент random-pic с использованием объединения модулей. В дальнейшем я буду называть этот компонент «хостом».
Для загрузки пульта в наш хост-проект необходимы следующие вещи:
Во-первых, основной проект также должен использовать Webpack 5:
// install Webpack 5 (beta version, v.20 is used in this example) npm i [email protected] -D
В своем файле index.html ему необходимо импортировать скрипт точки входа пульта ДУ:
<script src="https://josros.gitlab.io/random-pic-component/randomPicEntry.js"></script>
и до того, как custom-element удаленного может быть использован, хост должен импортировать удаленный с помощью функции динамического импорта, которая загружает компонент асинхронно:
после загрузки модуля создается custom-element, который добавляется в DOM.
Чтобы сообщить Webpack, как разрешить удаленный модуль (randomPic / component), файлу webpack.config.js также нужна некоторая дополнительная информация в основном проекте:
Имя модуля в этом проекте - интеграция, а конфигурация для пультов указывает Webpack разрешить randomPic как удаленный модуль.
Все остальные части не отличаются от стандартной конфигурации в Webpack ‹5. Полный файл webpack.config.js определяет, что ./src/index.js переносится в main.js с помощью загрузчика babel, о котором я упоминаю в файле index.html:
<script type=”module” src=”main.js”></script>
Если вы перейдете по адресу: https://josros.gitlab.io/random-pic-component-integration/, вы увидите удаленный компонент, отображаемый как часть основного проекта, в который компонент загружается с использованием федерации модулей Webpack 5.
Теперь, когда мы рассмотрели базовый сценарий интеграции с использованием объединения модулей Webpack 5, в следующем разделе будет показано, как объединение модулей обрабатывает общие модули.
Общие модули
Как вы могли заметить, над изображением в удаленном компоненте есть кнопка нравится. Такие же кнопки вы можете найти в основном проекте (как приложение).
Кнопка является частью проекта material-components-web-components и используется как зависимость в нашем удаленном компоненте, а также в основном проекте:
Поскольку мы не хотим, чтобы зависимость загружалась несколько раз, мы даем указание Webpack 5 разрешить эту зависимость за нас.
Для этого в файле проекта удаленного компонента webpack.config.js необходимо определить mwc-button как общий модуль, настроив конфигурацию ModuleFederationPlugin следующим образом:
По сравнению с версией, показанной ранее, здесь был добавлен общий объект. Определение сообщает Webpack, что mwc-button может использоваться всеми модулями. Однако для этого требуется определенная версия, которая в данном случае определена в файле package.json. Для получения дополнительной информации о том, как настроить общие объекты, вы можете прочитать эту статью.
mwc-button также должна быть определена как общий модуль в основном проекте. Вот как там настраивается конфиг ModuleFederationPlugin:
Запустив хост локально, мы можем увидеть, что происходит во время загрузки страницы:
localhost: 3013 - это место, где работает хост. index.html загружается первым. Далее идет файл randomPicEntry.js из нашего удаленного компонента на localhost: 3003. После этого загружается файл main.js, который, по сути, является пакетом хост-приложения. Оттуда mwc-button разрешается. Он исходит от localhost: 3013, потому что он используется в обеих частях.
axios, не является разделяемым модулем и используется только как зависимость внутри удаленного компонента, поэтому загружается оттуда. Наконец, комплект удаленных компонентов извлекается с localhost: 3003.
Ключевым моментом является то, что mwc-button загружается только один раз, даже если она используется в удаленном компоненте, а также в основном проекте.
Резюме
На момент написания этой статьи Webpack 5 все еще находится в стадии бета-тестирования, но, как пытается показать эта статья, он может преодолеть некоторые недостатки, которые в настоящее время существуют с интеграцией Micro Frontend.
Помимо преимущества, объединение модулей Webpack 5 обеспечивает масштабируемое решение интеграции кода приложения во время выполнения, оно решает проблему совместного использования зависимостей гибким способом. Если зависимость используется в нескольких модулях объединенного приложения, она автоматически использует самый высокий доступный пакет. При этом он учитывает многочисленные ограничения, настраиваемые для общей зависимости. В качестве запасного варианта он принимает зависимость, предоставляемую самим удаленным модулем. Это особенно полезно, поскольку во время выполнения условия могут измениться.
Создание портала для нескольких доменов, а также интеграция устаревших приложений, объединение модулей Webpack 5 не поможет нам во всех наших сценариях интеграции. Там, где i-frame были выбраны по уважительным причинам, проблемы с их интеграцией останутся. Но не меньше, чем наш предпочтительный подход к интеграции собственных веб-компонентов, Webpack 5 обещает стать эволюцией.
Сделав один шаг назад, чтобы добиться успеха с Micro Frontends или даже с разработкой программного обеспечения в целом, недостаточно выбрать правильный инструмент. Более того, важно привести команды в соответствие с рамками контекста и возложить на них сквозные обязанности. Последнее позволяет им напрямую оценивать и удовлетворять потребности клиентов, вместо того, чтобы увлекаться техническими мечтами. Тем не менее я убежден, что рассматривать команды как стратегические, а не подразделения, обеспечивающие доставку, гораздо важнее, чем наличие лучших технологий. По этой причине основным преимуществом Micro Frontend является то, что он напрямую поддерживает эту цель.