Привет! Недавно у нас в компании завершилось RnD по микрофронтендам, мы посмотрели подходы, протестировали некоторые идеи, и хотим поделиться с вами результатами. Если вы сейчас выбираете подход для использования микросервисов на фронтенде, этот пост может вам пригодиться как сводное сравнение особенностей, плюсов и минусов четырёх основных подходов.
Когда мы пытались понять потребности и присматривались к тому, какие решения в этой области есть у других, мы прошлись по компаниям, посмотрели, какие подходы в сфере микрофронтенда они используют. Несколько компаний приходили к нам и презентовали нам свои решения. Но так как большинство из этих решений были самописными, мы решили отказаться от рассмотрения данных концепций и посмотреть стандартные подходы.
И вот к чему мы пришли.
Мы выделили три основных потребности разработки на микрофронтенде.
разделить большие команды разработки фронтендов на несколько;
разрабатывать большие портальные приложения;
сократить порог входа в разработку для фронтенд‑разработчиков.
Подходов, которые мы рассмотрели, было четыре:
Single SPA,
Module Federation,
NPM modules,
Git Submodules.
Рассматривая каждый, мы описали, что это такое, выделили основные понятия, поверхностно посмотрели структуру и процесс создания приложения, CI/CD, и выделили отдельными блоками преимущества и недостатки каждого подхода.
Single SPA
Это фреймворк, который объединяет несколько javascript-микрофронтендов в одно фронтенд-приложение.
Особенности:
использование нескольких фреймворков на одной странице без обновления страницы,
разворачивание микрофронтендов независимо друг от друга,
написание кода, используя новые фреймворки, без переписывания существующего приложения,
ленивая загрузка кода для улучшения времени начальной загрузки.
Основные понятия
Import Maps позволяет импортировать приложения-модули, фреймворки, плагины и так далее, то есть на текущий момент Import Maps в процессе принятия в качестве стандарта, уже даже реализован в Chrome.
Layout engine — опциональный аддон для Single SPA, облегчает работу с DOM-ом, позволяет добавлять loader’ы на время загрузки микрофронтов, добавляет стандартные роутеры для страниц ошибок или перехода внутри приложения. Также он облегчает работу с SSR для Single SPA.
Root config — основная часть Single SPA приложения, именно в нем задается основной HTML-шаблон, подключается Import Maps и настраивается поведение микрофронтов на страницах приложения.
Что такое микрофронтенд в Single SPA?
Это микросервис, который существует в браузере. У каждого есть свой webpack config, каждый может быть запущен как отдельное приложение. В контексте Single SPA существует три вида микрофронтов.
Application. Это основной блок, именно он содержит в себе визуальную часть приложения, а ещё может содержать в себе роутинг, UI для разнообразных фреймворков существуют всякие хелперы, которые позволяют Single SPA работать с жизненными циклами фреймворка. В контексте view каждый Application — отдельное view-приложение со своими роутерами, сторами, страницами и прочим.
Parcel. Часть UI-приложения, которая будет использоваться разными фреймворками одновременно. Не содержит роутинг, здесь жизненный цикл у него определяется вручную.
Utility. Технический модуль, не содержит в себе роутинга или UI, может содержать сервисы по взаимодействию с API, общие какие-то стили, библиотеки и так далее.
Иными словами, основная структура Single SPA приложения — это root config, Import Maps и микрофронтенды. Визуально можно представить в таком виде.
Есть приложение, которое включает в себя микрофронты, и некий технический блок, которым все пользуются.
Процесс создания приложений в Single SPA
С помощью single-spa CLI мы создаем root-config,
Создаем import map’ы,
Настраиваем webpack приложение для root-config,
С помощью single-spa CLI создаем микрофронты,
Интегрируем все необходимые микросервисы в import map с нашего главного приложения.
И повторяем четвертый и пятый пункты, если требуется добавить еще несколько микрофронтов, создаем CI/CD.
CI/CD в Single SPA
Каждый микрофронт находится в отдельном репозитории, для каждого из них у нас настроена отдельная сборка вместе с root config’ом, чтобы можно было подключать другие микрофронты, и есть две вариации микрофронта: standalone (для отображения работы отдельного микрофронта, как показано на схеме, мы можем посмотреть работу микрофронта на некотором тестовом стенде) и SystemJS (модуль для интеграции в основной root config).
Если смотреть на основное приложение, то оно лежит в root config вместе с HTML layout, и в import maps включены все необходимые микрофронты (F1 и F2), это все развернуто на некоторых тестовых и продакшн серверах.
Плюсы Single SPA
Нет необходимости централизованно хранить микрофронтенды, так как они подгружаются в runtime по HTTP.
В одном приложении можно использовать несколько фреймворков, в список фреймворков входят React, Vue, Angular, их накопилось более тридцати.
Есть собственный SLA, который позволяет быстро поднимать микрофронты, то есть реально можно в течение пяти минут настроить микрофронт и подключить его.
При локальной разработке нет необходимости ничего поднимать, запускать у себя, то есть все микрофронты можно подключить по HTTP, то есть можно из продакшена, можно из теста.
Недостатки
Для работы необходимо использовать importMaps, root-config, плагины для фреймворков и всю систему для Single SPA.
Проблемы с документацией: хоть она довольно объемная, но не покрывает все вопросы. Иногда примеры приложений в ней оказываются более полезными, чем сама документация. Примеры там на React, так что под Vue требуется применение напильника.
Проблемы с SSR: его начали поддерживать только в последней версии single-spa, то есть существует один пример с SSR на React. Мы запустили SSR на Vue, но с большими костылями, то есть можно сказать, что в настоящее время SSR в single-spa недоработан.
При переходе с монолита на single-spa необходимо в корне менять CI/CD.
Также ImportMaps не является лучшим подходом к подключению модулей.
Module Federation
Module Federation — это плагин для webpack, который позволяет подключать удаленные модули в сборку webpack в runtime, то есть любой модуль, сборку которого поддерживает webpack, можно подключить через Module Federation.
Основные понятия
Микрофронт - это отдельный модуль из Module Federation.
Конфигурация Module Federation — кусок кода webpack, он содержит имя (наименование данного модуля, его будет необходимо использовать для подключения в другом приложении), file name - наименование файла, который будет содержать в себе код Module Federation, это вместо библиотеки, именно тип, который будет собран в Module Federation. Поддерживаются все типы модулей, которые поддерживает webpack.
new ModuleFederationPlugin({
name: 'mfHome',
filename: 'remoteEntry.js',
library: {
type: 'commonjs2',
name: 'remote5002'
},
exposes: {
'./home': './src/page/home.vue'
},
remote: {
'mgPage1': 'mfPage1@http://localhost:9091/remoteEntry.js'
},
shared: {
...deps,
vue: { singleton: false, eager: false },
vuex: { singleton: false, eager: true },
'vue-router': { singleton: true, eager: true },
}
})
Remote — список подключаемых микрофронтов.
Expose — компоненты, которые необходимо расшарить между приложениями.
Shared — управление зависимостями, что конкретно должно присутствовать в сборке, чтобы данный модуль вообще работал.
Структура приложения
Есть два приложения, APP1 и APP2, они через свои Module Federation предоставляют некие микросервисы MF1 и MF2. Главное приложение настроено так, что посредством Module Federation приложение забирает себе необходимые микросервисы и использует их.
Процесс создания приложения достаточно прост, состоит из трех этапов.
Мы создаем основное приложение-микрофронт, у которого настраиваем webpack и Module Federation.
Создаются все необходимые микрофронты, у них тоже настраивается webpack и Module Federation.
В конфигурацию основного приложения просто добавляются эти микрофронты. Каждый микрофронт имеет стандартный CI/CD, то есть настроена сборка standalone-приложения, оно раскатывается на некий тестовый стенд или на продакшн. Основное приложение лежит в отдельном репозитории, у него настроен webpack для подключения некоторых микросервисов, то есть далее CI/CD имеет стандартный вид.
Плюсы Module Federation
Все, что можно собирать через webpack, можно подключить как микрофронт, пусть это будет шрифт, CSS или отдельный компонент — все, что может собрать webpack, можно подключить.
Сборка в runtime, значит, можно настроить независимый деплой для каждого микрофронта.
Легкость подключения — достаточно добавить один плагин в настройки webpack.
Нет необходимости кардинально переделывать CI/CD.
Недостатки
Необходим webpack 5
Нет инструмента для обработки случая недоступности микрофронта
Не поддерживает версионирование, то есть у микрофронта всегда должна быть актуальная версия.
NPM modules
Изначально менеджер пакетов, позволяющий быстро и удобно доставлять переиспользованные компоненты, однако, он отлично нам подошел для приложений на микрофронтах.
Про него можно рассказать все в одном абзаце: микросервис — отдельный пакет, загружаемый в NPM, а NPM — это репозиторий пакетов. По процессу, по CI/CD тут тоже нечего говорить, так как приложение может быть написано и структурировано любым образом, то есть CI/CD может быть, а может и не быть. Если он есть, то где-то приложение можно посмотреть на каком-то тестовом стенде. Приложение должно быть написано таким образом, чтобы оно могло публиковаться в NPM. Есть некие стандарты, эти стандарты нужно учесть при разработке.
Плюсы
Единое хранилище для всех микрофронтов.
Легко создавать полноценные приложения для тестирования микрофронтов.
Легко работать с зависимостями, подключать микрофронты друг в друга, работать с разными версиями.
Нет необходимости кардинально переделывать CI/CD.
Недостатки
Сборка только в build time.
Сложности по взаимодействиям с разными командами микрофронтов, то есть очень сложный release management.
Git Submodules
Это подмодули Git, они позволяют вам сохранять один Git-репозиторий как подкаталог другого Git-репозитория. Такой подход дает нам возможность клонировать в наш проект какой-то другой репозиторий, при этом commit’ы хранить отдельно.
Основные понятия
Submodule — репозиторий, подключенный в другой репозиторий как подкаталог.
Файлик .gitmodules — файл, содержащий в себе информацию о подключенных в данных репозиторий submodules.
Внизу вы видите Git, в нем есть два репозитория с приложениями, у которых своя жизнь, и есть наше приложение. У нас есть доступ к этим двум репозиториям, и мы подключаем их как submodules нашего приложения.
Для нашего приложения, если смотреть на структуру, это всего лишь две отдельные папки, которые добавляются к нам в структуру. В каждой папке находится структура того приложения, которое мы добавили. Соответственно, мы можем обращаться к данным папкам и разрабатывать наши приложения, используя шрифты или CSS совсем другого репозитория.
Плюсы
Нет необходимости собирать микрофронты в какие-то модули или что-то еще, то есть здесь микрофронты распространяются в виде исходного кода.
Легко подключать микрофронты друг к другу, работать с разными версиями.
Недостатки
Сборка только в build time.
При рекурсивном добавлении микрофронтов друг к другу может сложиться ситуация, когда несколько копий одного микрофронта могут оказаться в основном приложении, то есть мы этого добились, мы увидели эту проблему, это решается переведением в плоскую структуру.
Отображение всей папки репозитория, даже файлов, не связанных с разработкой, то есть все, что у вас есть в репозитории, будет доступно в другом репозитории, если они будут использовать ваш репозиторий как submodule.
Что мы выбрали для себя и почему
Итого, после завершения RnD и подведения итогов мы единогласно пришли к выводу, что мы добавляем микрофронты в технологический радар нашего ЦК. Подходы Single SPA и Module Federation на сегодня запрещены к использованию нашими внутренними политиками.
А вот подходы с NPM и Git Submodules разрешены к использованию, но с некоторым ограничением: если нужно вставить в архитектуру работу с микрофронтами, то она, как минимум, должна быть согласована с куратором из ЦК. Микрофронты у нас начинают потихоньку использоваться, например, Git Submodules начали использовать в проекте CLUBPRO, там дизайнеры ведут репозиторий с картинками и иконками, а команда разработки уже забирает репозиторий к себе и использует у себя в работе.