Как фронтенд-разработчик, вы годами разрабатываете монолиты, хотя уже знаете, что это плохая практика. Вы делите свой код на компоненты, используйтеrequireилиimportИ добавьте пакет NPM, определенного в Package.json или установленном подмадичном репо, но в конечном итоге создают монолит. Пришло время изменить его.
Почему ваш код монолит?
Все интерфейсные приложения по сути являются монолитными приложениями, за исключением приложений, в которых реализованы микроинтерфейсы. Причина в том, что если вы разрабатываете с использованием библиотеки React и у вас есть две команды, обе команды должны использовать одну и ту же библиотеку React, и обе команды должны синхронизироваться при развертывании, а это всегда происходит во время конфликта слияния кода. Они не полностью разделены, скорее всего, они поддерживают одни и те же репозитории и имеют одинаковую систему сборки. Выход из монолита отмечен появлением микросервисов. Но это работает на бэкенде! 😱
Что такое микросервисы?
Самое простое объяснение микросервисов в целом состоит в том, что это метод разработки, который позволяет разработчикам независимо развертывать различные части платформы без ущерба для других частей. Возможность независимого развертывания позволяет им создавать изолированные или слабо связанные службы. Чтобы сделать эту архитектуру более стабильной, необходимо следовать некоторым правилам, которые можно обобщить следующим образом: у каждой службы должна быть только одна задача, и она должна быть небольшой. Так что команда, отвечающая за этот сервис, должна быть небольшой. Что касается размера команды и проекта,Джеймс Льюис и Мартин ФаулерОдно из самых крутых объяснений, сделанных в Интернете, звучит следующим образом:
В наших беседах с практикующими микросервисами мы видели разные размеры сервисов. Заявленный максимальный размер соответствует концепции Amazon о команде из двух пицц (то есть вся команда может быть обслужена двумя пиццами), что означает не более дюжины человек. В меньшем масштабе мы видели установки, в которых команда из шести человек поддерживает шесть сервисов.
Я нарисовал простой набросок, чтобы дать интуитивно понятное объяснение монолитов и микросервисов:
Как видно из схемы выше, каждый сервис в микросервисе — это независимое приложение, кроме UI. Пользовательский интерфейс по-прежнему цельный! Когда одна команда обрабатывает все сервисы, а компания масштабируется, фронтенд-команда начнет бороться и не сможет справиться с ней, что является узким местом этой архитектуры.
Помимо узких мест, эта архитектура также может вызвать некоторые организационные проблемы. Предположим, что компания растет и будет учитывать потребностикросс-функциональныйГибкие методы разработки для небольших команд. В этом распространенном примере владелец продукта, естественно, начал бы определять истории как внешние и внутренние задачи, в то время каккросс-функциональныйКоманда никогда не станет настоящейкросс-функциональныйОтделение. Это будет неглубокий пузырь, похожий на agile-команду, но внутренне разделенный. Дополнительная информация об управлении такой командой была бы очень важной работой. В каждом плане есть проблема, достаточно ли внешних задач или достаточно ли внутренних задач в спринте. Для решения всех описанных здесь проблем и многих других несколько лет назад придумалимикро интерфейсидея и стала быстро распространяться.
Устранение узких мест в микросервисах: Micro Frontends 🎉
Решение на самом деле довольно очевидное, использующее тот же принцип, который годами работал для серверных сервисов: разделите монолит внешнего интерфейса на небольшие фрагменты пользовательского интерфейса. Но пользовательский интерфейс не очень похож на сервис, это интерфейс между конечным пользователем и продуктом, и он должен быть последовательным и бесшовным. Что еще более важно, в эпоху одностраничных приложений все приложение работает в браузере клиента. Это уже не простые файлы HTML, а сложное программное обеспечение, достигающее уровня сложности. Теперь я чувствую, что определение микроинтерфейса необходимо:
Идея Micro Frontends состоит в том, чтобы рассматривать веб-сайт или веб-приложение как комбинацию функций, принадлежащих независимой команде. У каждой команды есть уникальная область бизнеса или миссии, чтобы делать то, на чем они сосредоточены и сосредоточены. Команды являются кросс-функциональными, разрабатывая сквозную функциональность от базы данных до пользовательского интерфейса. (micro-frontends.org)
Судя по моему опыту, многим компаниям действительно сложно напрямую внедрить представленную выше архитектуру. Многие другие имеют огромные устаревшие нагрузки, которые не позволяют им перейти на новую архитектуру. По этой причине критически важны более мягкие промежуточные решения, которые являются более гибкими, простыми в применении и безопасными для миграции. Описав архитектуру более подробно, я попытаюсь дать некоторое представление об архитектуре, которое подтверждает вышеизложенное предложение и позволяет использовать более гибкий подход. Прежде чем углубляться в детали, мне нужно установить некоторую терминологию.
Общая структура и некоторая терминология
Предположим, мы вертикально разделили общую структуру приложения по бизнес-функциям. В итоге мы получаем несколько небольших приложений, которые имеют ту же структуру, что и монолит. Но если мы добавим специальное приложение поверх всех этих небольших монолитных приложений, пользователь будет общаться с этим новым приложением, и оно объединит старый монолитный пользовательский интерфейс каждого небольшого приложения в одно. Этот новый слой можно назватьСшивание слоев, так как он берет сгенерированные части пользовательского интерфейса из каждого микросервиса и объединяет их в один для конечного пользователя.бесшовныйПользовательский интерфейс, который будет самой прямой реализацией микрофронтендов 🤩
Для лучшего понимания я называю каждое маленькое монолитное приложениеМикро приложение, поскольку все они являются автономными приложениями, а не просто микросервисами, все они имеют части пользовательского интерфейса, каждая из которых представляет сквозную бизнес-функцию.
Как мы все знаем, сегодняшняя клиентская экосистема универсальна и очень сложна. Поэтому этого простого решения недостаточно при реализации реального продукта.
проблема, которую нужно решить
Хотя этот пост — всего лишь идея, я начал использовать Reddit, чтобы обсудить эту идею. Благодаря сообществу и их ответам я могу перечислить некоторые проблемы, которые необходимо решить, и я постараюсь описать их по порядку.
когда у нас есть полностью независимаяМикро приложениеКак создать бесшовный и последовательный пользовательский интерфейс?
Ну, на этот вопрос нет серебряной пули, но одна из идей заключается в создании общей библиотеки пользовательского интерфейса, которая также является автономным микроприложением. Таким образом, все другиеМикро приложениеБудет зависеть от общей библиотеки пользовательского интерфейса для микроприложений. В этом случае мы просто создали общую зависимость и убили независимую.Микро приложениеидея.
Другая идея состоит в том, чтобы совместно использовать пользовательские переменные CSS на корневом уровне (CSS custom variables). Преимуществом этого решения является глобально настраиваемая тема между приложениями.
Или мы можем просто поделиться некоторыми переменными SASS и миксинами между командами приложений. Недостатком этого подхода является многократное внедрение элементов пользовательского интерфейса, иМикро приложениеВсегда проверяйте и проверьте целостность подобных элементов.
Как мы можем гарантировать, что одна команда не перезапишет CSS, написанный другой командой?
Одно из решений состоит в том, чтобы определить имена селекторов CSS CSS, которые были тщательно отобраны по имени микроприложения. Размещено по объему задачисплайс-слойуменьшит затраты на разработку, но увеличитсплайс-слойОбязанность.
Другое решение может состоять в том, чтобы заставить каждое микроприложение быть настраиваемым веб-компонентом (custom web component). Преимущество этого решения заключается в том, что браузер завершил дизайн диапазона, но он принимает цену: рендеринг на стороне сервера с помощью Shadow DOM практически невозможен. Кроме того, пользовательские элементы не имеют 100%Поддержка браузера, особенно ИЕ.
Как мы должны обмениваться глобальной информацией между микроприложениями?
Этот вопрос указывает на одну из самых больших проблем в этом вопросе, но решение довольно простое: HTML 5 имеет довольно много возможностей, о которых не знает большинство разработчиков интерфейса. Например,пользовательские событияЭто один из них, и это решение для обмена информацией в микро-приложениях.
В качестве альтернативы подойдет любая общая реализация pub-sub или наблюдаемая реализация T39. Если нам нужен более сложный обработчик глобального состояния, мы можем реализовать общий миниатюрный Redux, и таким образом мы можем реализовать более отзывчивую архитектуру.
Как мы можем выполнять маршрутизацию на стороне клиента, если все микроприложения являются автономными приложениями?
Этот вопрос зависит от каждой реализации дизайна, все основные современные фреймворки предоставляют надежные механизмы маршрутизации на стороне клиента, используя состояние истории браузера, вопрос заключается в том, какое приложение отвечает за маршрутизацию и когда.
Мой текущий прагматичный подход заключается в создании общего клиентского маршрутизатора, который отвечает только за маршрутизацию верхнего уровня, а остальные маршрутизаторы принадлежат соответствующим микроприложениям. Предположим, у нас есть/content/:id
определение маршрута. Общий маршрутизатор решит/content
, разрешенный маршрут будет передан в ContentMicroApp. ContentMicroApp — это автономный сервер, который будет использовать только/:id
позвонить.
Мы должны выполнять рендеринг на стороне сервера, но можно ли использовать микрофронтенды?
Рендеринг на стороне сервера — сложная задача. Если вы рассматриваете возможность сшивания iframesМикро приложениеТогда забудьте о рендеринге на стороне сервера. Точно так же веб-компоненты для задач сшивания не так эффективны, как iframe. Однако, если каждыйМикро приложениеспособный отображать его содержимое на стороне сервера, а затемсплайс-слойБудет отвечать только за подключение фрагментов HTML на стороне сервера.
Интеграция с устаревшими средами имеет решающее значение! Но как?
Для интеграции унаследованных систем я хотел бы описать свою собственную стратегию, которую я называю "прогрессирующее вторжение".
Во-первых, мы должны реализовать сшивающий слой, который должен функционировать как прозрачный прокси. Затем мы можем определить устаревшую систему, объявив подстановочный путь какМикро приложение:LegacyMicroApp. Таким образом, весь трафик будет направляться на уровень сшивания и будет прозрачно проксироваться в устаревшую систему, поскольку у нас пока нет других микроприложений.
Следующий шаг будет за намипервое пошаговое вторжение: мы удалим основную навигацию из LegacyMicroApp и заменим ее зависимостями. Эта зависимость будет реализацией с использованием новой блестящей технологии.Микро приложение:NavigationMicroApp.
Теперь слой конкатенации разрешает каждый путь какLegacy Micro App, который разрешает зависимости какNavigation MicroApp, и обслуживайте их, соединяя два.
Затем следуйте тому же шаблону через основную навигацию, чтобы перейти к следующему шагу.
Затем мы продолжим получать от Legacy MicroApp и повторять вышеописанное шаг за шагом, пока ничего не будет упущено.
Как настроить клиент так, чтобы нам не нужно было каждый раз перезагружать страницу?
сплайс-слойРешил проблему на стороне сервера, но не на стороне клиента. На стороне клиента, после загрузки вставленного фрагмента в виде бесшовного HTML, нам не нужно загружать все части каждый раз при изменении URL-адреса. Поэтому у нас должен быть какой-то механизм для асинхронной загрузки фрагментов. Но проблема в том, что эти фрагменты могут иметь некоторые зависимости, которые необходимо разрешить на стороне клиента. Это означает, что микрофронтенд решения должны обеспечивать загрузкуМикро приложениемеханизм и некоторые механизмы внедрения зависимостей.
Основываясь на вышеуказанных вопросах и возможных решениях, я могу обобщить все по следующим темам:
клиент
- хореография
- маршрутизация
- Изолировать микроприложения
- связь между приложениями
- Согласованность между пользовательскими интерфейсами микроприложений
Сервер
- рендеринг на стороне сервера
- маршрутизация
- управление зависимостями
Гибкая, мощная и простая архитектура
Так что эту статью стоит ждать с нетерпением! Наконец-то раскрыты основные элементы и требования к архитектуре микро-фронтенда!
Руководствуясь этими требованиями и опасениями, я начал разработку решения под названием microfe. 😎 Здесь я опишу архитектурные цели этого проекта, абстрактно выделив его основные компоненты.
Начать работу с клиентом легко, он имеет три отдельные магистральные структуры:Менеджер приложений, погрузчик, Routerи дополнительныйМагазин МикроАпп.
AppsManager
AppsManager — это ядро оркестрации микроприложений на стороне клиента. Основная функция AppsManager — создание дерева зависимостей. Когда все зависимости микроприложения разрешены, он создает экземпляр микроприложения.
Loader
Другой важной частью оркестровки микроприложений на стороне клиента является загрузчик. Загрузчик отвечает за получение неразрешенных микроприложений со стороны сервера.
Router
Чтобы решить проблему маршрутизации клиентов, я представил Routermicrofe. В отличие от обычных клиентских маршрутизаторов,microfФункционал ограничен, парсит не страницы, а микроприложения. Предположим, у нас есть URL/content/detail/13
и ContentMicroApp. при этих обстоятельствах,microfeРазобрать URL-адрес, чтобы/content/
, который вызовет ContentMicroApp/detail/13
раздел URL.
MicroAppStore
Чтобы решить проблему связи между микроприложением и клиентом микроприложения, я представил MicroAppStore.microfe. Он имеет аналогичную функциональность библиотеке Redux с одним отличием: он более гибок с асинхронными изменениями структуры данных и объявлениями редукторов.
Серверная часть может быть немного сложнее в реализации, но структура проще. содержит только две основные частиStitchingServerи многоМикроАппСервер.
MicroAppServer
MicroAppServerМинимальную функцию можно представить какinitа такжеобслуживать.
несмотря на то чтоMicroAppServerПервое, что он должен сделать, чтобы начать это использоватьЗаявление о микроприложениипередачаSticthingServerЗарегистрированная конечная точка, декларация определенаMicroAppServerМикро применениезависимости, Типыа такжеURL-схема.Я думаю, что нет необходимости упомянуть услуги, потому что нет ничего особенного.
StitchingServer
StitchingServerдляMicroAppServersПредоставляет конечную точку регистрации. когдаMicroAppServerзарегистрируйтесь вStichingServerчас,StichingServerбудет записыватьMicroAppServerзаявление о.
позже,StitchingServerАнализ запрошенного URL-адреса с использованием утвержденийМикросерверы приложений.
Парс МicroAppServerи все его зависимости, все относительные пути в CSS, JS и HTML будут начинаться с соответствующегоMicroAppServerПубличный URL имеет префикс. Еще один шаг — добавить уникальный элемент в селектор CSS.MicroAppServerИдентификатор для предотвращения конфликтов между клиентскими микроприложениями.
потомStitchingServerОсновная обязанность состоит в том, чтобы составить и вернуть цельную HTML-страницу из всех собранных частей.
Список других реализаций
Еще до того, как в 2016 году это назвали микрофронтендами, многие крупные компании пыталисьBigPipeдля решения Facebook и других подобных проблем. Сейчас идея проходит проверку. Компании всех размеров заинтересованы в теме и инвестируют время и деньги. Например, Zalando открыла исходный код своего решения под названием Project Mosaic. Я могу сказать, что микро иProject Mosaic.следует аналогичному подходу, но с некоторыми важными отличиями. В то время как microfe использует полностью децентрализованные определения маршрутов для повышения независимости каждого микроприложения, Project Mosaic предпочитает централизованные определения маршрутов и макетов для каждого пути. Таким образом, Project Mosaic позволяет легко проводить A/B-тестирование и создавать динамические макеты.
Есть и другие подходы к этой теме, например, использование iframe в качестве слоя сшивки, который, очевидно, находится не на стороне сервера, а на стороне клиента. Это очень простое решение, которое не требует большой серверной структуры и участия DevOps. Эта работа может быть выполнена только фронтенд-командой, что снижает организационную нагрузку на компанию при одновременном снижении затрат.
Уже есть фреймворк под названиемsingle-spa.Проект опирается на соглашение об именах каждого приложения для разрешения и загрузки микроприложений. Легко усваивать идеи и следовать шаблонам. Так что попробовать эту идею в вашей собственной локальной среде может быть хорошим первым введением. Но недостатком проектов является то, что вам нужно создавать каждое микроприложение особым образом, чтобы они могли хорошо использовать фреймворк.
последние мысли
Думаю, тема микрофронтендов будет обсуждаться чаще. Если тема сможет привлечь все больше и больше внимания компаний, она станет де-факто разработкой для больших команд. В ближайшем будущем любой front-end разработчик может иметь некоторое представление и опыт работы с этой архитектурой, что действительно полезно.
Подумайте о том, чтобы внести свой вклад
Я активно пробую микро-фронтенды и имею в виду высокую цель: создать фреймворк микрофреймворка, который может решить большинство проблем без ущерба для производительности, простоты разработки и тестируемости. Если у вас есть какие-либо умные идеи, пожалуйста, не стесняйтесь посетить мой репозиторий, открыть вопрос или связаться со мной через комментарии ниже или Twitter DM. Я буду там, чтобы помочь вам! 🙂
Перевод: Vincent.W
оригинал:Understanding Micro Frontends