1. Введение в микрофронтенды и концепцию Module Federation
Введение в микрофронтенды и концепцию Module Federation
Исторически сложилось так, что разработка пользовательских интерфейсов начиналась с создания единого, неделимого блока кода. Этот подход получил название монолитная архитектура. В монолитном приложении весь клиентский код — маршрутизация, бизнес-логика, компоненты интерфейса и работа с состоянием — находится в одном репозитории и собирается в единый пакет (бандл) перед отправкой в браузер.
На начальных этапах жизни продукта монолитный подход оправдывает себя. Он обеспечивает простоту настройки, легкость тестирования и быстрый старт разработки. Однако по мере роста продукта, увеличения кодовой базы и расширения штата инженеров монолит начинает демонстрировать серьезные недостатки.
Когда над одним проектом работают десятки человек, возникают организационные и технические барьеры. Время сборки проекта увеличивается экспоненциально. Если в начале пути Continuous Integration (CI) занимает пару минут, то в крупных проектах ожидание сборки может достигать часа. Любая, даже самая незначительная ошибка в одном модуле, способна привести к падению всего приложения.
Представим ситуацию: команда из 30 разработчиков трудится над крупным интернет-магазином. Разработчик из команды оформления заказов исправляет опечатку в тексте кнопки. Чтобы это изменение попало к пользователям, системе необходимо пересобрать весь проект целиком, прогнать тысячи тестов, никак не связанных с корзиной, и заново развернуть весь фронтенд. Если время сборки составляет 45 минут, а в день происходит 20 таких мелких изменений, суммарные потери времени становятся колоссальными.
> Микрофронтенды — это архитектурный подход, при котором единое монолитное приложение разделяется на множество небольших, независимых частей, каждая из которых разрабатывается, тестируется и развертывается автономно. > > Мартин Фаулер, эксперт в области архитектуры ПО
Архитектура микрофронтендов
Концепция микрофронтендов переносит принципы микросервисной архитектуры из бэкенда на сторону клиента. Вместо одного огромного приложения мы получаем набор самостоятельных мини-приложений, которые визуально объединяются в браузере пользователя, создавая иллюзию единого целого.
Каждая команда получает возможность выбрать собственный технологический стек, независимый цикл релизов и изолированную кодовую базу. Команда каталога может использовать React, в то время как команда блога предпочтет Vue.js, и их код не будет конфликтовать.
Сравнение подходов
| Характеристика | Монолитный фронтенд | Микрофронтенды | | :--- | :--- | :--- | | Развертывание | Развертывается целиком | Каждый модуль развертывается независимо | | Сборка | Единый длительный процесс | Быстрая сборка отдельных частей | | Масштабирование команд | Сложное, частые конфликты при слиянии кода | Простое, команды изолированы друг от друга | | Технологический стек | Единый для всего проекта | Возможность использовать разные фреймворки | | Отказоустойчивость | Ошибка может сломать всё приложение | Ошибка локализована в одном модуле |
Переход на новую архитектуру требует изменения мышления. Если количество разработчиков , внедрение микрофронтендов скорее усложнит процесс, добавив излишнюю инфраструктурную нагрузку. Однако при и наличии нескольких независимых бизнес-доменов, этот подход становится жизненно необходимым.
Эволюция интеграции: от iframe до Module Federation
Долгое время разработчики пытались реализовать микрофронтенды различными способами. Использовались iframes, которые обеспечивали идеальную изоляцию, но создавали огромные проблемы с производительностью и маршрутизацией. Затем популярность обрела интеграция во время сборки (через NPM-пакеты).
Интеграция через пакеты решала проблему изоляции кода, но возвращала нас к проблеме монолита: при обновлении пакета-микрофронтенда требовалось пересобрать основное приложение, чтобы изменения вступили в силу.
Настоящая революция произошла с выходом Webpack 5, в котором был представлен плагин Module Federation.
Module Federation — это технология, позволяющая JavaScript-приложениям динамически загружать код из других независимых сборок прямо во время выполнения (в рантайме), а не на этапе компиляции.
Ключевые термины Module Federation
Для понимания работы технологии необходимо разобраться в ее базовой терминологии. Архитектура строится вокруг взаимодействия двух основных ролей:
Представьте, что хост — это материнская плата компьютера, а удаленные модули — это видеокарта, оперативная память и звуковая карта. Вы можете заменить видеокарту на новую, не меняя материнскую плату. Точно так же вы можете обновить код удаленного модуля, и хост автоматически начнет использовать новую версию при следующем обновлении страницы пользователем, без пересборки самого хоста.
Как это работает на практике
В основе магии лежит специальный плагин ModuleFederationPlugin. Он анализирует граф зависимостей и создает специальные точки входа, через которые приложения могут общаться друг с другом.
Рассмотрим базовый пример конфигурации для удаленного модуля (Remote):
В этом конфигурационном файле мы определяем несколько важных параметров. Свойство name задает уникальное имя нашего модуля. Свойство filename указывает имя файла-манифеста, который будет сгенерирован Webpack. Этот файл содержит информацию о том, как хосту получить доступ к коду.
Самое интересное происходит в блоке exposes. Здесь мы буквально говорим: «Я хочу сделать компонент CartWidget доступным для внешнего мира по пути ./CartWidget».
Блок shared решает критическую проблему производительности. Если и хост, и удаленный модуль используют библиотеку React, браузеру не нужно скачивать ее дважды.
Допустим, размер библиотеки React составляет 130 КБ. Если на странице отображается один хост и три удаленных модуля, без механизма общих зависимостей браузер скачал бы КБ только одного фреймворка. Благодаря shared, библиотека скачивается ровно один раз, экономя 390 КБ сетевого трафика и значительно ускоряя время до первого взаимодействия с интерфейсом.
Интеграция в рантайме
Главное отличие Module Federation от классических подходов заключается в моменте объединения кода. При использовании NPM-пакетов код объединяется на сервере разработчика во время сборки. Если вы обновили пакет, вам нужно запустить процесс сборки заново.
В случае с Module Federation интеграция происходит непосредственно в браузере пользователя. Когда пользователь заходит на сайт, браузер скачивает хост-приложение. Как только пользователь переходит на страницу корзины, хост делает асинхронный запрос к серверу, скачивает актуальный код удаленного модуля cart_app и мгновенно встраивает его в интерфейс.
Это открывает невероятные возможности для масштабирования. Команды становятся по-настоящему независимыми. Они могут выкатывать обновления своих модулей десятки раз в день, и эти обновления будут моментально доступны пользователям без какого-либо вмешательства со стороны команды, отвечающей за хост-приложение.