В программировании есть такая штука, как микросервисы — это когда большие системы на бэкенде делятся на множество маленьких программ, каждая из которых выполняет свою задачу. Например, одна отвечает за авторизацию, другая — за базу данных, а третья — за рассылку писем.
А есть микрофронтенды. Это почти то же самое, что и микросервисы, только для интерфейса. С их помощью мы делим на отдельные программы не серверную часть, а сам пользовательский интерфейс.
Сегодня подробно разберём, что такое микрофронтенд, для чего он нужен, как применяется, где работает и кому это надо.
Что такое микрофронтенд
Микрофронтенд — это подход, при котором пользовательский интерфейс делится на независимые части. Каждая из этих частей, по сути, маленькое приложение, которое можно разрабатывать, обновлять и поддерживать отдельно от остальных. При этом все части объединяются в единый интерфейс.
Пример из жизни — Spotify. На первый взгляд это единое приложение, но на самом деле оно состоит из нескольких независимых частей:
Каждую часть делает своя команда. Причём они могут использовать разные технологии: панель — на React, список треков — на Angular. Для пользователя всё выглядит как единое приложение, но под капотом всё работает независимо друг от друга. Если навигация сайта обновляется, то это не влияет на основной контент. А ещё каждую часть можно разворачивать локально: если нужно обновить панель, не придётся перезапускать весь сайт.
На первый взгляд микрофронтенды похожи на микросервисы — те же независимые части, которые работают вместе. Но есть нюанс — микрофронтенды работают в браузере, а это накладывает ограничения:
- Один DOM. Все микрофронтенды располагаются в одной и той же структуре страницы. Если один добавит глобальные стили, это может затронуть другие части.
- Один Local Storage. Все части интерфейса используют одно хранилище данных, и это может вызвать конфликты.
- Одна адресная строка. У всех микрофронтендов общий URL, что усложняет их полную изоляцию.
В приложении микросервисы и микрофронтенды могут быть связаны так:
Микрофронтенды отвечают за интерфейс. Микросервисы (то есть бэкенд) обрабатывают данные, например пользовательские аккаунты или заказы. Всё это соединяется между собой через API-шлюз. Пользователь взаимодействует с интерфейсом, а тот отправляет запросы на сервер через этот шлюз.
Дальше посмотрим, как микрофронтенды упрощают разработчикам жизнь.
Какие проблемы решает микрофронтенд
Когда приложение маленькое, всё просто: одна команда, один фреймворк, весь код в одном месте. Если что-то пошло не так, все быстро собираются, обсуждают и исправляют. Но если проект разрастается, команд становится больше, а код превращается в монолит, то появляются проблемы:
- Всё связано. Изменяется кнопка в каталоге — ломается корзина. Почему? Сразу непонятно — нужно разбираться, где что-то пошло не так.
- Одна команда на всё. Чем больше приложение, тем больше задач, а времени — меньше. Команда не успевает всё делать, ошибки накапливаются.
- Ограничения в технологиях. Разработчик хочет попробовать новый фреймворк для корзины? Поскольку всё приложение на React, то никто не даст написать часть кода на Vue.
Если проект разросся, есть смысл внедрить микрофронтенды — разделить интерфейс на независимые части. Каждая часть — это самостоятельное приложение, которое можно менять, тестировать и обновлять отдельно.
Например, так сделали в компании Selectel. Разные команды работали над своими продуктами, и пока всё было в одном коде, возникали конфликты: кому-то нужно было обновить дизайн, а кто-то пытался внести новые функции. В компании решили перейти на микрофронтенды. Часть старого интерфейса была написана на Angular, и чтобы не переписывать всё сразу, разработчики заменяли фрагменты на новый Angular постепенно. Пока старая и новая части интерфейса работали вместе, пользователи этого даже не замечали. После перехода всё стало проще и зоны ответственности разделились: каждая команда отвечала только за свой модуль, и больше никто никому не мешал.
Но микрофронтенды — это не универсальное решение. Они хороши для больших приложений, где есть несколько команд, каждая из которых работает над своей частью. Разные части интерфейса требуют разных технологий. Но если приложение маленькое, то микрофронтенды только добавят лишней сложности.
Логика микрофронтенда
Микрофронтенды строятся на трёх принципах: автономность, модульность и минимальное взаимодействие между частями.
Пользователь заходит на сайт, и первым делом перед ним появляется шапка — это маленький микрофронтенд, который загружается мгновенно. Затем подгружается каталог товаров. А корзина включается только тогда, когда пользователь решит что-то купить. Микрофронтенды загружаются по мере необходимости, что позволяет экономить ресурсы.
Чтобы всё работало связно, микрофронтенды могут обмениваться информацией через события, общее хранилище, передачу колбэк-функций и так далее.
Допустим, пользователь нажимает кнопку «Добавить в корзину» в каталоге. В этот момент микрофронтенд «Каталог» инициирует событие с данными о выбранном товаре. Событие передаётся через глобальный объект document и содержит всю информацию в формате, который понимают другие микрофронтенды. Микрофронтенд «Корзина» подписан на такие события и ожидает сигнала. Когда событие достигает его, он обрабатывает полученные данные, добавляет товар в свой список и сразу обновляет пользовательский интерфейс, чтобы отобразить изменения.
При взаимодействии через события микрофронтенды остаются независимыми. «Каталогу» не нужно знать, как устроена «Корзина», её внутреннюю логику или структуру. Его задача — просто отправить сигнал в общую систему. А «Корзина» сама определяет, что делать с полученными данными.
Другой вариант — общее хранилище. Когда пользователь нажимает кнопку «Добавить в корзину» в каталоге, микрофронтенд «Каталог» отправляет данные в общее хранилище. Микрофронтенд «Корзина» подписан на изменения в хранилище и автоматически получает уведомление, что появился новый товар. После этого он также обновляет свой интерфейс, добавляя товар в список или меняя счётчик.
Также чтобы микрофронтенды не мешали друг другу, у каждого из них:
- Свои стили. Делается это через CSS-модули или Shadow DOM.
- Свои зависимости. Если один блок работает на React 16, а другой — на React 18, они не конфликтуют.
В общем, код остаётся изолированным, и каждый микрофронтенд отвечает только за свою задачу.
Как собрать всё вместе
Главный элемент в системе микрофронтендов — контейнер. Это центральное приложение, которое загружает микрофронтенды, контролирует маршрутизацию и обеспечивает взаимодействие. Микрофронтенды обмениваются данными через контейнер или напрямую. Каждый микрофронтенд развёртывается отдельно. У него свои зависимости, свой сервер, и он обновляется независимо от других.
Чтобы собрать всё приложение из микрофронтендов, разработчики используют разные инструменты. Каждый из них подходит для своих задач и проектов:
- Podium. Этот фреймворк позволяет рендерить микрофронтенды на стороне сервера. Фреймворк берёт фрагменты интерфейса от каждого микрофронтенда и собирает их воедино перед отправкой пользователю. Подходит для проектов, которые строятся с нуля, но требует глубоких знаний серверных технологий.
- Single SPA. Самый популярный инструмент, который объединяет микрофронтенды на одной странице. Подходит для постепенной миграции с одного фреймворка на другой.
- Module Federation. Технология Webpack, которая позволяет микрофронтендам делиться кодом и компонентами в реальном времени. Устраняет дублирования кода, а общие компоненты или стили обновляются только в одном месте.
- Монорепозиторий. Такой подход позволяет хранить все микрофронтенды в одном репозитории. Это помогает избежать проблем с совместимостью версий и упрощает сборку проекта. Например, если каталог и корзина используют одну библиотеку, их совместимость всегда под контролем.
Микрофронтенды и компоненты — в чём разница?
Во фронтенд-разработке давно прижился компонентный подход. Приложения делятся на отдельные части-функции — кнопки, списки, карточки товаров. Каждый компонент отвечает за небольшую задачу: отобразить кнопку «Купить», список товаров или модальное окно. Это удобно, пока приложение небольшое.
И на первый взгляд может показаться, что микрофронтенды — это просто крупные компоненты. Но это не одно и то же.
Главное отличие: микрофронтенды — это полностью независимые части интерфейса, а компоненты зависят от общей инфраструктуры приложения.
Компоненты — это инструмент для небольших задач в рамках одного приложения. Они зависят от одного набора библиотек, одного фреймворка и одного процесса сборки. Нельзя написать разные компоненты на разных фреймворках.
Микрофронтенды — это решение для крупных проектов, где нужно разделить приложение на независимые части. В растущем проекте микрофронтенды дают гибкость и масштабируемость, которую не обеспечат компоненты.
Если проект работает на Angular, а нужно перейти на React, то микрофронтенды позволяют сделать это постепенно. Сначала можно переписать одну часть на React и сделать её отдельным модулем — другая часть приложения при этом продолжит работать на Angular. Контейнер свяжет старый и новый код в единое приложение. Пользователи не заметят изменений, а разработчики смогут безболезненно мигрировать на новые технологии.