Микро-фронтенд. Обзор архитектуры и рекомендуемые практики +11



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

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

Как устроен микро-фронтенд?

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

Вот основные концепции, на которых выстроена микро-фронтендовая архитектура

Технологическая независимость

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

Изолированность кода, создаваемого разными командами

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

Создание командных префиксов

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

Нативные возможности браузера предпочтительнее созданных вами API

Для коммуникации не пишите глобальную систему «публикация/подписка», а пользуйтесь событиями браузера. Если будет необходимость создать API для совместной работы нескольких команд, постарайтесь держать его максимально простым.

Обеспечение надежного веб-дизайна

Все фичи должны быть полезными, даже если JavaScript выполнить не удается. Чтобы улучшить воспринимаемую производительность, пользуйтесь универсальным рендерингом и прогрессивными усовершенствованиями.  

Каковы наилучшие практики, принятые в микро-фронтенде

Различные практики, при помощи которых реализуется микро-фронтендовая архитектура:

  1. Единый мета-фреймворк для SPA (одностраничных приложений) комбинирует на одной странице сразу несколько приложений без необходимости обновлять страницу; таковы, в частности, React, Vue, Angular, т.д.

  2. Множество одностраничных приложений находятся по разным URL. Для приложений с разделяемой функциональностью нужно использовать компоненты NPM или Bower.

  3. Обособление микро-приложений в Iframes при помощи Windows. API для отправки сообщений и библиотеки нужны для координации. IFrames разделяют API, предоставляемые их родительским окном.

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

Библиотеки компонентов, зависящие от стека главного приложения, различные компоненты и разделы приложения разрабатываются как библиотеки, после чего их «требует» главное приложение. Следовательно, главное приложение состоит из разнородных компонентов.

Как взять на вооружение микро-фронтендовую архитектуру?

Вот как перейти на микро-фронтендовую архитектуру и реализовать микросервисное тестирование с применением веб-компонентов:

Интеграция в браузере

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

Веб-компоненты

Веб-компоненты обеспечивают создание многоразовых единиц, импортируемых в веб-приложения. Они подобны виджетам, импортируемым на любую веб-страницу. В настоящее время они нативно поддерживаются в браузерах Chrome, Opera и Firefox. Если тот или иной браузер не поддерживает веб-компоненты нативно, совместимость достигается при помощи полифиллов JavaScript. Веб-компоненты состоят из 4 элементов, которые могут использоваться отдельно или вместе -

  1. Собственные элементы

  2. Теневая DOM

  3. Импорты HTML

  4. Шаблоны HTML

Собственные элементы

При помощи собственных элементов (Custom Elements) создаются собственные HTML-теги и элементы. Каждый элемент сопровождается своими CSS-стилями и скриптами. Если нужно создавать собственные теги, применять стили CSS и добавлять поведения, то это делается при помощи скриптов. Единственный требуемый стандарт – ставить дефис во избежание конфликта с новыми HTML-элементами. Например, при создании списка оформляемых заказов, в котором присутствуют как собственные элементы, так и собственные теги, получаются веб-компоненты и обратные вызовы жизненного цикла элементов. Эти обратные вызовы жизненного цикла позволяют определять поведения, специфичные для разработки компонентов. Обратные вызовы жизненного цикла, используемые с собственными элементами, таковы:

  1. CreatedCallback – определяет поведение, происходящее, когда компонент прошел регистрацию.

  2. AttachedCallback – определяет поведение, происходящее, когда компонент вставлен в DOM.

  3. DetachedCallback – определяет поведение, происходящее, когда компонент отсутствует в DOM.

  4. AttributeChangedCallback - определяет поведение, происходящее, когда добавляется, меняется или удаляется атрибут.

Наилучший пример с собственными элементами:

class CheckoutBasket extends HTMLElement {

constructer (){...} is created

connectedCallback (){...}  attached to DOM

attributeChangedCallback (attr , oldVal , newVal)  someone changed an attribute

disconnecteCallback () {...}  removed from DOM, cleanup events that have been registered
}

Собственные элементы, применяемые по умолчанию - stencil, svelte, SkateJS, AngularElements, hyperHTML, т.д.

Теневая DOM

Теневая DOM от основной DOM – это API, сочетающий HTML, CSS и JavaScript внутри веб-компонента. Когда они находятся внутри компонента, они отделены от основной объектной модели документа. Такое отделение напоминает следующую ситуацию: пользователь занимается созданием сервисов API, а потребитель сервиса API ничего не знает о его внутреннем строении, так как все, что важно для пользователя – это запросы к API. У такого сервиса нет никакого доступа к внешнему миру, за исключением запрашивания API других сервисов. Подобные возможности были представлены и в веб-компонентах. Обращения к их внутреннему поведению извне не происходит, ха исключением случаев, когда это разрешено преднамеренно. Аналогично, теневая DOM никак не затрагивает основную DOM того документа, в котором находятся компоненты. Основной способ связи между веб-компонентами – это срабатывание событий.

HTML-импорты

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

  • Оболочка – это наиболее внешняя обертка, состоящая из контейнера для компонента и палитры компонентов. В ее состав должны входить контроллеры или представления, позволяющие пользователю оперировать компонентами.

  • Контейнер – это фактическая корневая точка, куда должен внедряться HTML-код вложенных приложений. Для всех вложенных приложений у него должна быть единая точка входа.

  • Палитра компонентов позволяет управлять вложенными приложениями, активными в настоящий момент.

HTML-шаблоны

HTML-шаблон – это элемент, содержащий содержимое с клиентской части, которое не отображается при загрузке страницы. Давайте попробуем понять реализацию микро-фронтендовой архитектуры на примере следующего приложения, написанного на React.Js. Хорошо, когда веб-приложения разрабатываются независимо друг от друга, чтобы при изменении некоторого элемента он не блокировал и не повреждал другие. Вот почему в этом примере новое приложение React должно собираться, запускаться и развертываться отдельно, а другие приложения, с которыми ему придется обмениваться информацией – расценивать как сервисы. Так, в нижеприведенном примере создается заголовок для веб-страницы. Здесь используется React.js. Это новомодная вещь. Давайте воспользуемся create-react-app для быстрой начальной загрузки:

npm install -g create-react-app

create-react-app head

cd head/

npm start

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

Затем создадим файл под названием server.js в корне проекта; он будет запускать сервер express, а также сделаем серверный рендеринг react:

const path = require('path');

const fs = require('fs');

const express = require('express');

const React = require('react');

const App = require('./transpiled/App.js').default;

const { renderToString } = require('react-dom/server');

const server = express();

server.get('/', (req, res) => {

const htmlPath = path.resolve(__dirname, 'build', 'index.html');

 fs.readFile(htmlPath, 'utf8', (err, html) => {


const rootElem = '
const renderedApp = renderToString(React.createElement(App, null)); res.send(html.replace(rootElem, rootElem + renderedApp)); server.use(express.static(‘build’));const port = process.env.PORT || 8080;server.listen(port, () => { console.log(`App listening on port ${port}`); });

Этот скрипт укореняется там, где находится элемент react (App), отображает его в строку и отправляет в HTML, прежде, чем выдать пользователю. Позже React поднимется на базе этого уже отображенного компонента. Но он работает на NodeJS, а Node JS не понимает JSX или других сравнительно новых видов синтаксиса, например, import, поэтому для транспиляции этого кода перед запуском на сервере использовался babel:

npm install --dev babel-cli babel-preset-es2015

Добавляем две задачи в раздел со скриптами в package.json, чтобы это запустить:

"transpile": "NODE_ENV=production babel src --out-dir transpiled --presets es2015,react-app",

"start:prod": "NODE_ENV=production node server.js"

Вот и все. Теперь запускаем заголовок при помощи:

npm run build

npm run transpile

npm run start:prod

Почему микро-фронтенды так важны?

В наше время, когда появляются все новые веб-приложения, клиентская часть все укрупняется, а важность серверной части снижается. Большая часть кода относится к микро-фронтендовой архитектуре. А монолитный подход с большими веб-приложениями не работает. Должен быть инструмент для разбиения такого монолита на сравнительно мелкие модули, действующие независимо друг от друга. Решение для этой проблемы – микросервисное устройство фронтенда. Код клиентской части пишется исключительно на чистом JavaScript и с применением любых javascript-фреймворков, с которых или на которые осуществлялась миграция.

Каковы достоинства микро-фронтендовой архитектуры?

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

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

  • Способствует непрерывному развертыванию

  • Тестирование сильно упрощается; когда нужно проверить небольшое изменение, не приходится затрагивать все приложение.

  • Реновация фронтенда – упрощается косметическое обновление

  • Повышенная надежность и удобство в поддержке

Заключительные замечания

Вы убедитесь, что в микро-фронтендовой архитектуре как ядро кода, так и интеграция устроены невероятно просто. Одна из критически важных проблем – стандартизация принципов UI/UX. Универсальное решение – опираться на стилевое руководство, среди прочего – на Material Design, Bootstrap. Чтобы все работало гладко, нужно наладить коммуникацию в команде, разработать стандарты и правила, минимизировать трения между разными командами. Все эти практики, рекомендуемые в микро-фронтендовой архитектуре, помогают решить важнейшую проблему: масштабируемость. Бывают приложения, которые начинают разбухать, а с таким ростом сопряжены многочисленные проблемы и конфликты. Если разделить код между командами и правильно организовать его «логистику» - придет качество, будут учтены технологические тренды, а мир обогатится новыми быстрыми решениями.




Комментарии (13):

  1. raamid
    /#23541040 / +2

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

  2. nin-jin
    /#23541088 / -1

    ПСБанк недавно проводил хакатон на тему микрофронтендов. Так мы там демонстрировали подход $mol на эту тему. И не смотря на то, что $mol не был рекомендуемой технологией, нам удалось попасть в тройку финалистов. Просто потому, что мы смогли за пару дней сделать больше и качественнее в свободное от безделья время. Гляньте, наш питч - это кардинально иной подход, вобравший лучшее из обоих миров:

  3. merrick_krg
    /#23541508 / +10

    Что мне нравится в микрофронтенде, что любой аргумент который используется как достоинство, можно использовать как и недостаток)

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

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

    А править баги связанные с ядром микрофронтов это просто адовый труд.

    Я вижу только пару причин использовать микрофронтенд:

    1. переезд на другую технологию, когда требуется итеративный переход.

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

    Технологию настолько наводящую хаос в проекте не встречал со времён редакса)

    Холивар опен)

    • i360u
      /#23541948 / +1

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

    • MentalBlood
      /#23542078

      А что не так с редаксом? Вроде ж его так активно продвигали и использовали, причем создавалось ощущение, что он именно про наведение порядка (а не про магию [хаоса])

      • markelov69
        /#23542802 / +4

        А что не так с редаксом?

        Проблемы:
        — Иммутабильность.
        — Тонны абсолютно лишнего кода.
        — Гнусная производительность (особое «спасибо» иммутабильности).
        — Не удобно читать/писать данные.
        Преимущества:
        — Отсутствуют.

        Поэтому все адекватные люди уже давным давно используют MobX.

    • Sm1le291
      /#23542090 / +1

      Работал и видел несколько очень крупных проектов, от 1 до 3млн строк

      каждый раз улыбаюсь, когда люди оценивают сложность проекта по количеству строк)

      • merrick_krg
        /#23543572 / +2

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

    • artchalet
      /#23543004

      Холивар опен)

      Вроде на хабре в основном +- согласятся с вами. Насчет микросервисов хайпа было много, но в реальные проекты очень немного перешло.

      • merrick_krg
        /#23543582

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

        • DmitryKazakov8
          /#23543728

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


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


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

    • atomic1989
      /#23547068

      Пробовали что-то из аля микрофронтенда во времена, когда и не пахло этой темой, на базе SharePoint. Воспоминания как про срочную службу в армии). Рано еще переходить, инфраструктура окружения не готова

  4. i360u
    /#23541958 / +2

    Статья - ужасна, куча ошибок и неточностей как в примерах кода так и в описании технологий. Я понимаю конечно, что перевод, но тут, видимо, и сам исходник - треш.