В технологиях наблюдается своеобразное явление: каждые несколько лет мы коллективно решаем, что предыдущая архитектурная модель была, по сути, бесполезной, а новый блестящий подход — это ответ на все вопросы. Мы живём в такой момент с микрофронтендами. Шумный маркетинг реален. В блогах повсюду заявляют, что монолиты мертвы, что корпоративные приложения должны использовать микрофронтенды и что если вы всё ещё строите монолиты в 2025 году, то программируете как в 2000 году.

Однако вот в чём дело: вам продают повествование, не показывая сносок.

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

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

Механизм шумихи и его побочные эффекты

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

Чего они не подчёркивают: у их команды есть выделенные ресурсы для платформенного инжиниринга, сложная инфраструктура мониторинга и система CI/CD, которая вызвала бы зависть у большинства компаний. Они также, вероятно, потратили миллионы, чтобы узнать, что не работает.

Это предвзятость отбора, замаскированная под лучшую практику.

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

Но вот что отказывается признавать шумиха: у большинства приложений пока нет этих проблем. И навязывание архитектуры команде, которая в ней не нуждается, похоже на покупку инфраструктуры балансировки нагрузки корпоративного уровня, когда у вашего стартапа 100 активных пользователей в день.

Где монолиты фактически превосходят микрофронтенды

Позвольте мне привести вам цифры, которые редко попадают в вдохновляющие посты в LinkedIn.

Производительность — неудобная правда архитектуры микрофронтендов. При прямом сравнении монолитные приложения обычно демонстрируют превосходную начальную производительность загрузки. Хорошо построенный монолит загружает меньше байтов, загружается быстрее и требует меньше сетевых запросов. Один процесс сборки webpack может оптимизировать активы глобально таким образом, который распределённые микроприложения просто не могут.

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

Да, такие техники, как Module Federation, помогают, но они являются обходным путём для фундаментального ограничения архитектуры. Единственная монолитная сборка остаётся более оптимизируемой по своей природе.

Скорость разработки на ранних этапах

Разработка монолитного приложения объективно проще. У вас одна кодовая база, один конвейер сборки, один процесс развёртывания. Младший разработчик может клонировать репозиторий и внести значимый вклад в течение нескольких часов, а не дней. Когда вам нужно действовать быстро — во время разработки MVP, на ранних этапах итерации продукта или при проверке соответствия рынку — это имеет огромное значение.

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

Тестирование и отладка

Комплексное тестирование (end-to-end) значительно проще в монолите. Вы запускаете одно приложение, и вся система доступна. Вашему тестеру не нужно ждать запуска нескольких серверов, координировать состояние между службами или обрабатывать нестабильные сетевые зависимости между частями вашего собственного фронтенда.

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

Структура затрат

И давайте поговорим о деньгах, потому что об этом мало кто говорит. Каждому микроприложению в вашей архитектуре, скорее всего, понадобятся:

  • своя инфраструктура тестирования;
  • свой конвейер развёртывания;
  • свой мониторинг и Observability;
  • своя инфраструктура хостинга (даже если она контейнерizada, вы умножаете операционную площадь);
  • своя система дежурств (своего рода — зависимости всё равно создают переплетение).

У монолита всё это есть в одном экземпляре. Разница в стоимости немаленькая. Для компаний, создающих продукт с нуля, и для большинства организаций среднего рынка накладные расходы на инфраструктуру микрофронтендов являются конкретным бизнес-бременем, а не абстрактной архитектурной проблемой.

Действительное дерево принятия архитектурных решений

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

Выберите МОНОЛИТ, если:
├─ Ваша команда фронтенда состоит менее чем из 10–15 разработчиков
├─ Вы находитесь в первые 2–3 года эволюции продукта
├─ Вам нужно быстро выпускать и итерировать стратегию продукта
├─ Ваше приложение вписывается в единый технологический стек
├─ Производительность и время загрузки являются критическими метриками
└─ У вас ограниченные ресурсы DevOps/платформенного инжиниринга
Выберите МИКРОФРОНТЕНДЫ, если:
├─ У вас 30+ разработчиков, работающих над фронтендом одновременно
├─ Командам нужна подлинная независимость развёртывания
├─ Вам нужно интегрировать сторонние или внешние приложения
├─ Разным командам требуются разные технологические стеки по уважительным причинам
├─ Вы можете позволить себе выделенный платформенный инжиниринг
└─ Организационная автономия стоит компромисса по производительности

Ключевая фраза в этом списке: «вы можете позволить себе выделенный платформенный инжиниринг». Микрофронтенды без хорошей платформенной поддержки создают хаос. Я видел это.

Практический пример: когда я вернулся к монолиту

Я хочу поделиться реальным примером, потому что теория без практики — это просто философия.

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

Реальность: наш процесс сборки занимал 18 минут. У нас было семь отдельных репозиториев. Чтобы поделиться простой утилитной функцией, требовалось опубликовать пакеты npm и координировать обновление версий. Исправление безопасности в общей зависимости означало координацию трёх отдельных развёртываний. Адаптация новых разработчиков означала понимание семи систем сборки, семи процессов развёртывания и семи различных конвенций.

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

Мы объединили всё обратно в монолит. Та же команда, тот же код (в основном), унифицированная система сборки.

Время сборки: 4 минуты. Время до достижения новой продуктивности разработчика: сократилось с двух недель до трёх дней. Накладные расходы на координацию развёртывания функций: практически устранены. Производительность: улучшилась по всем метрикам.

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

Сравнение систем сборки: практический взгляд

Позвольте мне показать вам, как это выглядит на практике.

Монолитный подход

// webpack.config.js - единый источник правды
const path = require('path');
module.exports = {
  entry: './src/index.tsx',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[contenthash].js',
  },
  optimization: {
    runtimeChunk: 'single',
    splitChunks: {
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          priority: 10,
        },
        common: {
          minChunks: 2,
          priority: 5,
          reuseExistingChunk: true,
        },
      },
    },
  },
  // Единая сборка, глобальная оптимизация, без дублирования
};