Единообразие — это не цель, которой можно достичь. Это подписка, которую вы оплачиваете. Каждая инженерная организация рано или поздно приходит к этому, обычно в тот момент, когда вторая или третья команда начинает коммитить в тот же репозиторий. Независимо от того, запускаете ли вы единый монолит на React или созвездие независимо развертываемых фронтендов, вы не оптимизируете систему для нулевых затрат. Вы просто выбираете, какой счет придет вам в конце квартала.

Налог на координацию монолитов

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

По мере роста команды этот налог растет вместе с ней. Узкие места в код-ревью смещаются от технических вопросов к социальным. Репозиторий со ста двадцатью контрибьюторами не масштабируется линейно; он масштабируется комбинаторно. Очереди слияния (merge queues) забиваются. Релизные циклы (release trains) растягиваются на дни. Дизайн-система становится политическим институтом, требующим управляющего совета для одобрения нового варианта кнопки. Монолит сопротивляется изменениям не из вредности. Он сопротивляется изменениям, потому что каждая поверхность является общей, и каждое изменение требует консенсуса.

Проведение границ

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

Теория выглядит чисто. Если команда Shipping рефакторит свой слой маршрутизации, команда Billing не должна об этом беспокоиться. Если интерфейсу поиска нужно развертываться пять раз в день, он не должен ждать, пока страница настроек аккаунта завершит свои сквозные (e2e) тесты. Границы превращают организационное трение в технические интерфейсы. Но проведение этой черты никогда не бывает бесплатным.

Инфраструктурный счет

Микрофронтенды создают платформенные затраты. Вам нужно shell-приложение, способное компоновать фрагменты во время выполнения (runtime). Вам нужен конвейер развертывания, который понимает, как собрать артефакты из нескольких задач сборки в единую связную страницу. Если вы используете Webpack Module Federation, теперь вы управляете версиями общих зависимостей в независимо собранных бандлах. Если вы используете iframes, вы отлаживаете междоменное взаимодействие (cross-origin messaging) и боретесь со сдвигами макета (layout shifts). Если вы используете web components, вы занимаетесь версионированием кастомных элементов в распределенном графе, где обновление одной команды может перекрывать (shadow) обновления другой.

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

Когда затраты смещаются

Рассмотрим среднюю SaaS-компанию с четырьмя фронтенд-командами, использующими одно приложение Next.js. Развертывание происходит дважды в день после трехчасового запуска CI. Когда команда Shipping хочет отрефакторить навигацию, они отправляют запрос на комментарии (RFC), обновляют пути импорта по всему дереву и ждут две недели, пока команда Billing подкорректирует свои интеграционные тесты. Затраты — это координация, проще некуда.

Они переходят на микрофронтенды. Теперь каждая команда владеет своей вертикалью и деплоит в продакшн по собственному графику. Первый месяц это ощущается как свобода. А затем появляется баг. Глобальный хедер не отрисовывается в Safari, потому что команда Shipping обновила CSS-in-JS библиотеку, которая конфликтует с базовыми стилями, внедренными командой Search. Отладка требует участия трех дежурных инженеров, общего «war room» и болезненного отката двух сервисов, потому что shell-приложение кэширует манифесты модулей. Затраты сместились. Они не исчезли.

Арифметика масштабирования

Ни одна из моделей не является бесплатной. Стартапу из пятнадцати человек не нужна команда платформы. Накладные расходы на module federation, независимые конвейеры развертывания (deployment pipelines) и распределенное контрактное тестирование съедят всю их скорость разработки (velocity). Им следует платить координацией, потому что координация обходится дешево. Они могут договориться о паттерне управления состоянием (state management pattern) за десятиминутный разговор и выпустить его в тот же день.

Предприятие из пятисот человек с дюжиной бизнес-подразделений, работающих в разных квартальных циклах, сталкивается с противоположной проблемой. «Налог на координацию» становится экспоненциальным. Релизные поезда (release trains) занимают недели. Численность платформенных инженеров (platform engineering) уже является бюджетной реальностью, поэтому добавление микрофронтенд-инфраструктуры — это предельные издержки, а не новая статья расходов. Для них обмен встреч по согласованию на графы развертывания — это рациональная арифметика.

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

Выбор валюты

Если вы выбираете микрофронтенды, четко осознавайте, что именно вы покупаете. Вы приобретаете автономность команд и независимость развертывания. Будьте готовы оплатить следующее:

  • Runtime-оболочку (shell), которая управляет композицией, маршрутизацией и границами ошибок (error boundaries) между фрагментами.
  • Политику общих зависимостей, ориентированную на стратегию дедупликации, а не на общую логику реализации.
  • Межкомандное контрактное тестирование для каждой поверхности интеграции.
  • Единую систему наблюдаемости (observability), способную коррелировать клик пользователя между распределенными бандлами.
  • Модель управления производительностью, поскольку ни одна команда не владеет финальной полезной нагрузкой (payload), которую загружает браузер.

Если вы выбираете монолит, будьте честны относительно счета. Вы покупаете простоту в обмен на синхронизацию. Будьте готовы платить за:

  • Совместное владение кодом и ритуалы управления, необходимые для поддержания его целостности.
  • Темп релизов, определяемый самым медленным интеграционным тестом в конвейере.
  • Широкий радиус поражения (blast radius) при обновлении библиотек.
  • Ползучую реальность, в которой ваши самые быстрые инженеры будут двигаться со скоростью ваших самых осторожных.

Главный вывод

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