Архитектура микроинтерфейса — это архитектура, аналогичная микросервисам, которая применяет концепцию микросервисов к стороне браузера, то есть превращает веб-приложения из единого монолитного приложения вПриложение, объединяющее несколько небольших интерфейсных приложений в одно..
В результате изменение состоит в том, что эти клиентские приложения могутРаботать независимо,Самостоятельная разработка,Автономное развертывание. и они должны быть доступны вобщие компонентыПараллельная разработка одновременно — этими компонентами можно управлять через NPM или Git Tag, Git Submodule.
Уведомление: Фронтенд-приложение здесь относится к странице одного приложения с разделением фронтэнда и бэкэнда, только на этом основании имеет смысл говорить о микро-фронтенде.
В сочетании с моими последними шестью месяцами вмикро интерфейсС точки зрения практики и исследований архитектура микроинтерфейса обычно может быть реализована следующими способами:
- Перенаправление нескольких приложений с помощью маршрутизации HTTP-сервера
- Разрабатывайте механизмы связи и загрузки поверх различных фреймворков, таких какMooaиSingle-SPA
- Создайте единое приложение, объединив несколько независимых приложений и компонентов.
- фреймы. Использование iFrames и настраиваемых сообщений
- Создавайте приложения с помощью чистых веб-компонентов
- Создавайте с помощью веб-компонентов
Разные методы подходят для разных сценариев использования, и, конечно же, их можно использовать и в комбинации. Итак, давайте рассмотрим их один за другим и сделаем некоторые технические приготовления для будущей эволюции архитектуры.
Базовое предзнаменование: маршрутизация распространения приложений -> приложение распределения маршрутизации
В монолитном внешнем и монолитном внутреннем приложении существует типичная функция, заключающаяся в том, что маршрутизация выполняетсяРамкаДля распространения фреймворк назначает маршрут соответствующему компоненту или внутренней службе. Что делает микросервис в этом процессе, так это вызываетвызов функциисталудаленный вызов, такие как удаленные HTTP-вызовы. И микро передняя часть аналогична, она будетВызовы компонентов в приложениистановится более мелкозернистымКомпонентные вызовы между приложениями, то есть изначально мы просто раздавали маршрут на компонентное выполнение приложения, но теперь нам нужно найти соответствующее приложение по маршруту, а затем раздать его на соответствующий компонент приложением.
Бэкенд: вызов функции -> удаленный вызов
В большинстве веб-приложений типа CRUD также есть несколько очень похожих шаблонов, а именно: Home -> List -> Details:
- Домашняя страница используется для отображения конкретных данных или страниц пользователям. Эти данные обычно ограничены по количеству и разнообразию моделей.
- Список, то есть агрегация моделей данных, обычно характеризуется набором данных определенного типа, и вы можете увидеть как можно больше.Сводка данных(Например, Google возвращает только 100 страниц), обычно вы видите страницы результатов поиска Google, Taobao и JD.com.
- Детали, показывающие как можно больше данных.
Ниже приведен пример среды Spring для возврата на домашнюю страницу:
@RequestMapping(value="/")
public ModelAndView homePage(){
return new ModelAndView("/WEB-INF/jsp/index.jsp");
}
Для страницы сведений это может выглядеть так:
@RequestMapping(value="/detail/{detailId}")
public ModelAndView detail(HttpServletRequest request, ModelMap model){
....
return new ModelAndView("/WEB-INF/jsp/detail.jsp", "detail", detail);
}
Тогда в случае с микросервисами это будет выглядеть так:
@RequestMapping("/name")
public String name(){
String name = restTemplate.getForObject("http://account/name", String.class);
return Name" + name;
}
В этом процессе серверная часть добавляет службу обнаружения службы для управления взаимосвязью между различными микрослужбами.
Внешний интерфейс: вызов компонента -> вызов приложения
Формально между роутингом одного front-end фреймворка и одного back-end приложения нет большой разницы:Шаблоны для разных страниц возвращаются по разным маршрутам.
const appRoutes: Routes = [
{ path: 'index', component: IndexComponent },
{ path: 'detail/:id', component: DetailComponent },
];
И когда мы его микросервисим, он может стать маршрутом приложения А:
const appRoutes: Routes = [
{ path: 'index', component: IndexComponent },
];
Плюс маршрутизация для приложения B:
const appRoutes: Routes = [
{ path: 'detail/:id', component: DetailComponent },
];
А суть дела вот в чем:Как распределить маршруты к этим разным приложениям. В то же время он также отвечает за управление различными интерфейсными приложениями.
Маршрутно-распределенные микрофронтенды
Маршрутно-распределенные микрофронтенды, то есть маршрутизация разных сервисовРаспространение в различные независимые клиентские приложенияначальство. Обычно этого можно добиться с помощью обратного прокси-сервера HTTP-сервера или маршрутизации, поставляемой с инфраструктурой приложения.
В настоящее время архитектура микро-интерфейса, распространяемая через маршрутизацию, должна быть наиболее приемлемым и простым решением «микро-интерфейса». Но так больше похожеАгрегация нескольких интерфейсных приложений, т. е. мы просто собираем вместе эти разные интерфейсные приложения, чтобы они выглядели как единое целое. Но это не так, каждый раз, когда пользователь переходит из приложения А в приложение Б, ему часто приходится обновлять страницу.
В проекте несколько лет назад мы работали надУстаревшая система переписана. У нас есть план миграции:
- Во-первых, используйтеГенерация статического сайтаДинамически генерировать домашнюю страницу
- Во-вторых, используйте стек планов React для рефакторинга страницы сведений.
- Наконец, замените страницу результатов поиска
Миграция всей системы происходит не сразу, а поэтапно. Следовательно, при выполнении разных шагов нам нужно запустить эту функцию, поэтому нам нужно использовать Nginx для распределения маршрутизации.
Ниже приведен пример конфигурации Nginx на основе распределения маршрутов:
http {
server {
listen 80;
server_name www.phodal.com;
location /api/ {
proxy_pass http://http://172.31.25.15:8000/api;
}
location /web/admin {
proxy_pass http://172.31.25.29/web/admin;
}
location /web/notifications {
proxy_pass http://172.31.25.27/web/notifications;
}
location / {
proxy_pass /;
}
}
}
В этом примере запросы на разные страницы распределяются по разным серверам.
Впоследствии мы использовали аналогичный подход в других проектах, главным образом потому, что:Сотрудничество между командами. Когда команда достигает определенного размера, нам приходится сталкиваться с этой проблемой. В дополнение к этому, есть также проблема с апгрейдом Anglar для прыжков со скалы. Итак, в этом случае пользователь использует Angular для перезаписи фронтенда, а бэкенд продолжает использовать Angular.js и другие технологические стеки. В разных сценариях есть несколько схожих технических решений.
Таким образом, в этом случае он работает для следующих сценариев:
- Различия между различными технологическими стеками относительно велики, и их трудно совместить, мигрировать и трансформировать.
- Проект не хотел тратить много времени на дооснащение этой системы
- Существующие системы будут заменены в будущем
- Системные функции уже очень полные, и новых требований в принципе не будет.
В случае выполнения вышеуказанного сценария, если для лучшего взаимодействия с пользователем, для решения проблемы также можно использовать iframe.
Создайте контейнер с iFrame
iFrame — очень старая технология, которую все считают обычной, но она всегда работала очень хорошо.
HTML-элемент iframe
<iframe>
Представляет вложенный контекст просмотра, фактически встраивая другую HTML-страницу в текущую страницу.
iframe может создать совершенно новую независимую среду хостинга, что означает, что наши интерфейсные приложения могут работать независимо друг от друга. Есть несколько важных предпосылок для использования iframe:
- Сайт не требует SEO-поддержки
- иметь соответствующиеМеханизм управления приложениями.
Если мы делаем платформу приложений, мы будем интегрировать сторонние системы в нашу систему или системы под управлением нескольких команд разных отделов, очевидно, это хорошее решение. Некоторые типичные сценарии, такие как миграция традиционных настольных приложений в веб-приложения:
Если этот тип приложения слишком сложен, его необходимо разделить на микросервисы. Поэтому при использовании iframe нам нужно сделать две вещи:
- дизайнМеханизм приложения управления
- дизайнМеханизм связи приложений
загрузочный механизм. При каких обстоятельствах мы будем загружать и выгружать эти приложения, в этом процессе какой вид анимации перехода используется, чтобы пользователь выглядел более естественно.
механизм связи. Создавайте прямо в каждом приложенииpostMessage
Мероприятия и прослушивание — недружественные вещи. Это слишком навязчиво для самого приложения, поэтомуiframeEl.contentWindow
Получение объекта Window элемента iFrame — более упрощенный подход. В последующем необходимоОпределить набор спецификаций связи: в каком формате используется имя события, когда начинать прослушивание событий и т. д.
Заинтересованные читатели могут взглянуть на фреймворк микроинтерфейса, написанный автором ранее:Mooa.
В любом случае, никакой пользы для нашего KPI в этом году iframe не принесет, так что давайте строить колесо.
Самодельные приложения, совместимые с фреймворком
Будь то Angular на основе веб-компонентов или React на основе VirtualDOM, существующие интерфейсные фреймворки неотделимы от базового элемента DOM HTML.
Тогда нам просто нужно:
- Представьте или создайте модель DOM в соответствующем месте страницы.
- Когда пользователь работает, соответствующее приложение загружается (инициируя запуск приложения), и приложение может быть удалено.
Первую проблему, создание DOM, легко решить. Вторая проблема совсем непростая, особенно удаление слушателя из DOM и соответствующего приложения. Когда у нас другой стек технологий, нам нужно целенаправленно разрабатывать набор такой логики.
несмотря на то чтоSingle-SPAВ нем уже есть обработка запуска и удаления для большинства фреймворков (таких как React, Angular, Vue и т. д.), но он все еще не подходит для использования в продакшене. Когда я разработал приложение с архитектурой микроинтерфейса для фреймворка Angular на основе Single-SPA, я, наконец, решил переписать свой собственный фреймворк, а именноMooa.
Хотя этот метод относительно сложен в использовании, он более удобен для последующей настройки и обслуживания. Независимо от проблем с пользовательским интерфейсом, возникающих при каждой загрузке приложения, единственными существующими рисками могут быть:Сторонняя библиотека несовместима.
Однако технически болееправо хвастаться, интереснее. Кроме того, как и в случае с iframe, мы все еще сталкиваемся с рядом мелких проблем:
- Необходимо разработать механизм управления приложениями.
- Для приложений toC с высоким трафиком будет большое количество запросов при их первой загрузке.
И мы должны разделить приложение, и мы хотим блабла..., что еще мы можем сделать?
Компонуемая интеграция: виджет вашего приложения
Комбинированная интеграция, то есть черезразработка программного обеспеченияНа этапах перед сборкой, во время сборки, после сборки и на других этапах приложение разделяется и рекомбинируется пошагово.
Исходя из этого определения, его нельзя рассматривать как микро-интерфейс — он может соответствовать трем элементам микро-интерфейса, а именно:Работать независимо,Самостоятельная разработка,Автономное развертывание. Однако с функцией Lazyload компонентов front-end framework, то есть соответствующие бизнес-компоненты или приложения загружаются только при необходимости, и это выглядит как микро-front-end приложение.
В то же время, поскольку все зависимости и Pollyfills максимально загружаются с первого раза, стили CSS не нужно загружать повторно.
Общие способы:
- Создавайте компоненты и приложения независимо друг от друга, генерируйте файлы фрагментов, а затем выполняйте сборку.классифицироватьСгенерированный файл фрагмента. (Этот подход больше похож на микросервисы, но дороже)
- Разрабатывайте компоненты или приложения независимо во время разработки, комбинируйте компоненты и приложения во время интеграции и, наконец, создавайте единое приложение.
- Во время выполнения загрузите среду выполнения приложения, а затем загрузите соответствующий код приложения и шаблоны.
Отношения между приложениями показаны на следующем рисунке (на рисунке игнорируется «внешний микросервис»):
Такой подход кажется идеальным, поскольку позволяет нескольким командам параллельно работать над созданием подходящих результатов.
Однако, прежде всего, у него есть серьезное ограничение:должны использовать ту же структуру. Для большинства команд это не проблема. Команды, внедряющие микросервисы, не будут использовать разные языки и технологии для разработки из-за внешнего интерфейса микросервисов. Конечно, если вы хотите использовать другие фреймворки, это не проблема, нам просто нужно совместитьСамодельные приложения, совместимые с фреймворкомможет удовлетворить наши потребности.
Во-вторых, есть ограничение использования этого метода, а именно:Спецификация! ****Спецификация! ****Спецификация!. При принятии этой схемы нам потребуется:
- Равномерная зависимость. Унифицируйте версии этих зависимостей, и добавлять их нужно по одной при введении новых зависимостей.
- Спецификация компонентов и маршрутов приложения. Избегайте конфликтов между различными приложениями, поскольку имена этих компонентов конфликтуют.
- Построить комплекс. В некоторых сценариях нам нужно модифицировать систему сборки, в других нужны сложные архитектурные скрипты.
- Поделитесь общим кодом. Это, очевидно, вопрос, с которым приходится часто сталкиваться.
- Разработка спецификаций кода.
Таким образом, это больше похоже на проблему разработки программного обеспечения.
Теперь у нас есть четыре варианта, каждый со своими плюсами и минусами. Очевидно, что комбинация была бы более идеальным подходом.
Принимая во внимание ограничения существующих и часто используемых технологий, давайте снова взглянем в долгосрочную перспективу.
Создан с использованием чистой технологии веб-компонентов
В процессе изучения веб-компонентов для разработки архитектуры микроинтерфейса я попытался написать свою собственную структуру веб-компонентов:oan. После добавления некоторых базовых функций веб-интерфейса я обнаружил, что этот метод особенно подходит длякак краеугольный камень микро-фронтендов.
Веб-компоненты — это другой набор технологий, которые позволяют создавать многократно используемые настраиваемые элементы, функциональность которых инкапсулирована вне вашего кода, и использовать их в своих веб-приложениях.
Он в основном состоит из четырех технических компонентов:
- Пользовательские элементы, которые позволяют разработчикам создавать собственные элементы, такие как файлы .
- Теневой DOM или теневой DOM обычно прикрепляется к основному документу DOM и может управлять связанными с ним функциями. Этот теневой DOM не может напрямую контролироваться другими DOM основного документа.
- HTML-шаблоны, т.е.
<template>
и<slot>
элемент для написания шаблонов разметки, которые не отображаются на странице. - Импорт HTML для импорта пользовательских компонентов.
Каждый компонент состоит изlink
Введение этикетки:
<link rel="import" href="components/di-li.html">
<link rel="import" href="components/d-header.html">
Затем в соответствующих файлах HTML создайте соответствующие элементы компонента и напишите соответствующую логику компонента. Типичная архитектура приложения веб-компонентов показана на следующем рисунке:
Вы можете видеть, что этот метод очень похож на способ, которым мы использовали iframe выше, и компонент имеет свой собственный независимыйScripts
иStyles
и соответствующее доменное имя для индивидуального развертывания компонентов. Однако он не так красив, как представлялось, и его необходимо использовать напрямую.чистыйСложность создания интерфейсных приложений с веб-компонентами заключается в следующем:
- Перепишите существующее интерфейсное приложение. Да, теперь нам нужно доделать функционал всей системы с помощью Web Components.
- Верхние и нижние экосистемы несовершенны. Отсутствие соответствующей поддержки некоторых сторонних элементов управления, из-за чего jQuery достаточно популярен.
- Архитектура системы сложная. Когда приложение разбивается на один компонент за другим, связь между компонентами становится особенно большой проблемой.
ShadowDOM в веб-компонентах больше похож на новое поколение интерфейсных контейнеров DOM. К сожалению, не все браузеры могут полностью поддерживать веб-компоненты.
Создавайте с помощью веб-компонентов
Веб-компоненты сейчас слишком далеки от нас, но создание клиентских приложений с помощью веб-компонентов — это архитектура, ориентированная на будущее. Или в будущем мы можем начать создавать наши приложения таким образом. К счастью, уже есть рамки для такой возможности.
На данный момент существует два способа объединения веб-компонентов для создания микроинтерфейсных приложений:
- Используйте веб-компоненты для создания независимых от фреймворка компонентов, а затем импортируйте эти компоненты в соответствующий фреймворк.
- Добавьте существующий фрейм в веб-компоненты, аналогичный форме iframe.
Первый представляет собой подход, основанный на компонентах, или аналогичный переносу будущей «устаревшей системы» на будущую архитектуру.
Интеграция существующих фреймворков в веб-компоненты
Существующие веб-фреймворки уже имеют некоторые формы, которые могут поддерживать веб-компоненты, такие как createCustomElement, поддерживаемый Angular, который может реализовать компонент в виде веб-компонентов:
platformBrowser()
.bootstrapModuleFactory(MyPopupModuleNgFactory)
.then(({injector}) => {
const MyPopupElement = createCustomElement(MyPopup, {injector});
customElements.define(‘my-popup’, MyPopupElement);
});
В будущем появится больше фреймворков, которые можно будет интегрировать в приложения веб-компонентов с помощью такой формы.
Веб-компоненты, интегрированные в существующие фреймворки
Другой способ что-то вродеStencilВ форме встраивайте компонент непосредственно в компонент в форме веб-компонентов, а затем напрямую ссылайтесь на него в соответствующих компонентах, таких как React или Angular.
Вот пример ссылки на созданные трафаретом веб-компоненты в React:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import 'test-components/testcomponents';
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();
В этом случае мы можем создавать независимые от фреймворка компоненты.
Тот же Stencil по-прежнему поддерживает только некоторые последние браузеры, такие как: Chrome, Safari, Firefox, Edge и IE11.
Сложный
Сложный, да, просто выберите несколько из вышеперечисленных категорий и объедините их вместе.
Я не буду говорить глупости~~.
в заключении
Итак, какое микроинтерфейсное решение нам следует использовать? Ответ см. в следующем «Руководстве по быстрому выбору Micro Frontend».
Релевантная информация: