
Всем привет. Меня зовут Михаил, я - фронтенд-разработчик в Лиге Цифровой Экономики.
В последнее время я пробую себя в должности руководителя направления фронтенд-разработки, однако я хочу с вами поделиться опытом разработки приложения с применением Webpack Module Federation, о том, какие задачи приходилось решать и проблемы, которые возникли на этом пути. Не буду вдаваться в теорию о микрофронтах и module federation, об этом уже много написано и предполагается, что вы знакомы с базовой настройкой. Мы же поговорим о самом «вкусном», некоторые моменты будут опущены в целях сосредоточения на деталях.
Вместо предисловия
На момент написания статьи (21.01.2022) проект находится в предрелизном состоянии и была уже выпущена альфа-версия, которую клиент передал своим потенциальным покупателям. Проект сам по себе с точки зрения бизнеса представляет собой коробочное решение, в виде АРМ системного администратора со следующими возможностями:
- Граф топологии доменов и сайтов 
- Удаленный рабочий стол прямо в браузере (noVNC) 
- Установка ОС, ПО на машины пользователей по сети 
- Управление пользователями, принтерами и др. 
- Подсистема оповещений через WebSocket и многое другое. 
Однако, необходимо вернуться примерно на год назад.
Как все начиналось
Был обычный рабочий день, я тогда был еще рядовым разработчиком и трудился над другим проектом, который был на Vue. Как говорится, ничего не предвещало беды. Ко мне подошел тимлид и сказал: «Заканчивай задачи и как будешь готов, мне надо будет с тобой поговорить. Меня обдало холодным потом, потому как я только переехал из другого города и вышел с удаленки. В действительности, все оказалось несколько проще:
– Итак, Миш, у нас новый проект. На React. Я хочу перевести тебя туда.
– Да без проблем, - обрадовался я. – А что за проект?
– Проект специфический, я всех деталей не знаю, я только готовил прототип. Тебе надо будет поговорить с архитектором. А, да, там будут микрофронты. В общем, чуть позже более детально обсудим, я тебе пока дам доступы и кину приглашения в телеге в чаты нужные.

Тут меня холодным потом обдало во второй раз. Дело в том, что в свободное время я с друзьями пишу пет-проект, если вкратце, то игровой сервер для GTA V на движке, в котором крутится Chromium Embedded Framework, а фронты (мы свои писали на React) выводятся как куча iframe один над другим и иногда возникала проблема шаринга состояния. По сути, очень похоже на те же микрофронты. Вспомнив всю боль, с которой я столкнулся в пете, я немного приуныл и стал ждать деталей.
От лирики переходим к деталям. Какие вводные я получил:
- Я один фронтендер на проекте. 
- У заказчика есть MVP, необходимо «просто его доработать» (с) 
- Фронт разделяется на ядро и дочерние приложения. Заказчик хочет в любой момент добавлять/удалять приложения без больших работ по фронту. 
- У каждого приложения есть манифест – некоторая метаинформация + навигация 2 уровня и ниже. Этот манифест ядро запрашивает у сервера и тем самым отображает доступные модули системы 
- У заказчика есть UI-kit 
Как вы понимаете, некоторые пункты с течением проекта сильно изменились. Так, например, постепенно команда фронта в пике достигала 5 человек, а от MVP не осталось почти и следа.
Когда я получил MVP на руки, я полез «под капот» где я обнаружил самописный механизм подключения микрофронтов, который достаточно сильно связан со структурой манифеста приложения, а так же Babel и Redux Toolkit. Остальное было не так интересно.

По структуре MVP был просто монолитом, где в папке pages лежали отдельно микрофронты и все это через хитрую таску поднималось на нескольких локальных серверах – сервер ядра, проксирующий и заодно еще сервер с микрофронтом (в dev и watch режимах). Ядро стучало в проксирующий сервер в режиме разработки, который ходил локально в папку с микрофронтом и отдавал его. Выглядело все довольно странно, учитывая предпочтения заказчика и очевидной задачей от тимлида стал распил этого добра на отдельные репозитории.
Окончив всю эту работу, начался цикл разработки, но ситуация выше меня коробила. Список проблем, которые возникли в самом начале:
- Для рабочего ноутбука поднимать несколько серверов стало трудоемкой задачей. Добавляем сюда открытый браузер, Figma, Spotify и по уровню шума можно подумать, что у меня на столе мини Байконур 
- Приложение монтировалось, но оставляло за собой кучу мусора, к тому же еще и не всегда корректно размонтировалось. Особенно остро вопрос мусора стал тогда, когда я заметил, что стили UI kit подключается банально тегом <style> в шапку и никак не удаляется и такая ситуация постоянно повторяется для каждого микрофронта 
В целом, проблем с точки зрения конечного пользователя не было никаких проблем и сначала я решил закрыть на это глаза, но на первой же приемке на наличие мусора обратил внимание заказчик. Моему праведному гневу не было предела, да и разрабатывать было жутко неудобно и долговато. Конструктивно описав ответ на некоторые претензии, я отправился решать свои проблемы.
Микроинфаркты от микрофронтов
Этот раздел я хочу посвятить тем нервным моментам, которые пришлось пережить.
Поиски по теме микрофронтов дали неоднозначные результаты. С одной стороны, была куча информации о теории. С другой - почти ничего о практике. Тогда я наивно полагал, что уже сформированы лучшие практики, но реальность оказалась плачевной. Естественно, тогда чуть ли не из каждого угла трубили о Module Federation, и я думал быстро запрыгнуть в паровоз хайпа и умчаться в светлое будущее, которое умные дяди и тети проложили до меня. Отдельно отмечу, что Single SPA тогда странным образом прошел мимо меня, но Module Federation сильно меня зацепил, т.к. в нем я увидел едва ли не решение всех своих проблем:
- Можно избавиться от самописного механизма, который тяжело поддерживать 
- Можно избавиться от дополнительного локального сервера для разработки 
- В локальной разработке я сильно ближе становлюсь к реальным условиям работы 
- Сильно привлекла фича шаринга пакетов между микрофронтами, потому что эта мысль пришла едва ли не сразу и на обсуждениях с тимлидом пришли как раз к выводу о том, что было бы неплохо определять наличие того же React на странице. 
Естественно, сразу же перейти на Module Federation не получилось. Почти потеряв надежду, т.к. я потратил 3 недели (точнее выходных по субботам и воскресеньям) на адаптирование приложений и не получалось ничего. Работал и прототип тимлида на своем механизме и примеры с гитхаба Module Federation, но именно мой проект не работал. Я долго анализировал сначала код, потом конфиги вебпака и не найдя очевидных ответов я попросту решил с 0 переписать приложения. И… оно заработало!
Микроинфаркт №1. Настройка Webpack
Итак, что нужно для настройки ModuleFederation. Выводом из примеров и статей стало то, что нужно всего лишь добавить ModuleFederationPlugin:
const ModuleFederationPlugin = require('webpack').container.ModuleFederationPlugin;
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'app1',
    }),
  ],
};
И в дочернем приложении:
const ModuleFederationPlugin = require('webpack').container.ModuleFederationPlugin;
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'app2',
      filename: 'remoteEntry.js',
      exposes: {
        './Widget': './src/Widget',
      },
    }),
  ],
};
Казалось бы, что тут не так? Да все тут так, но проблема оказалась всего лишь в одной строке и не в этом месте:

Это одна из проблем, с которой пришлось столкнуться и это проблема потому, что нигде не была указана важность publicPath в output. Именно тут я лично застрял надолго.

Микроинфаркт №2. Загрузка дочерних приложений
Первая проблема решена – микрофронты заводятся, все хорошо. Кроме одного: необходимо вручную прописывать все приложения. По сути, в этом ничего плохого нет, но это никак не коррелирует с требованиями ТЗ, да и в последствии все дописывать руками тоже лень.
Вторая проблема заключалась в том, что все-таки надо делать загрузку динамически, учитывая манифест. Сам манифест выглядит следующим образом:
{
  "id": "someapp",
  "moduleName": "SomeApp",
  "entrypoint": "someapp.js",
  "menuItem": {
    "path": "/foo",
    "label": "Бла-бла",
    "description": "какое-то описание",
    "icon": "hi",
    "options": [
      {
        "label": "2 уровень навигации",
        "path": "/bar"
      }
    ]
  },
  "routerPath": "/app",
  "weight": 1
}Это уже конечная вариация манифеста любого дочернего приложения и все-бы ничего, но в конце марта прошлого года не было никаких подсказок о том, как делать динамику. В разделе advanced api был пример, вокруг которого я начал придумывать свой велосипед, но вместо колес получались квадраты. И примерно в конце апреля, когда я уже во второй раз думал бросить все, я наткнулся на статью, из которой честно стырил позаимствовал и механизм динамической загрузки (части кода можно найти на гитхабе и документации webpack), и хук по загрузке скриптом, который полностью разрешил проблему «мусора» в <head>. 
Микроинфаркт №3. Состояние
Redux. Как много было о нем написано и сказано, и, наверняка мне достанется в комментариях за слова ниже, но все-таки я осмелюсь. Очевидна идея объединения сторов приложений и недолго копая я наткнулся на Redux Reducer Injection Example. Вроде бы все классно, но тут возникли самые большие сложности с адаптацией.

Во-первых, инжектить редьюсер в хост приложение мне показалось странным в том смысле, что необходим корректный механизм очищения «хвостов» от дочернего приложения при размонтировании. Мне в голову хороший вариант так и не пришел
Во-вторых, к этому моменту начался этап интеграции с беком и стал вопрос о полноценном переходе на саги. Я, если честно, не сторонник ради одной библиотеки тянуть еще 10, когда можно обойтись одной.
В-третьих, специфика приложения не обязывает директивно управлять дочерним приложением. По сути, оно просто предоставляет слот для монтирования (см схему выше) и содержит кое-какую информацию о его адресе и т.д. (напомню, решение коробочное, т.е. у каждого клиента свой экземпляр системы, который он размещает, где и как ему угодно).
В-четвертых, а почему бы просто не передавать стор сверху вниз, а не снизу вверх? А также вообще объединить их, одновременно оставив независимыми.
В-пятых, концептуально каждое приложение содержит отдельный набор сущностей (компьютер, группа компьютеров, ПО, домен, сайт и т.д.) и они нигде и никак не пересекаются, имея свое независимое состояние. Представляю перед собой огромного вида стор, сразу же захотелось отделить котлеты от мух, т.к. это попросту Домены.
Ответ нашелся сразу в виде MobX. Он полностью удовлетворяет всем потребностям, не тянет за собой шлейф из библиотек, великолепно работает с промисами и генераторами, а так же прямо в документации говорит, как объединить сторы. Забегая вперед, скажу, что при расширении команды вхождение в MobX заняло несколько дней для джунов, что сэкономило много времени на дистанции.
Микроинфаркт №4. Роутер, роутинг и history
На самом деле это не столько проблема Module Federation, сколько, наверняка, я ошибся в проектировании и пересборке приложения из MVP. Например, у меня напрочь отказался работать BrowserRouter при монтировании дочернего приложения, при этом HashRouter работает как надо. И из-за некоторых ошибок при построении роутов пришлось держать 2 разные версии history для хоста и дочернего приложения из-за проблем энкодирования кириллицы в URL и передачи некоторых параметров в Django. Если у кого есть мысли не этот счет, был бы рад услышать какой вы используете роутер.
Микроинфаркт №5. Шаринг модулей
Не думаю, что станет откровением тот факт, что шаринг модулей – это киллер-фича Module Federation. Давайте посмотрим на опции в конфиге:
- eager – говорит о том, что данный модуль необходимо «жадно» потреблять при старте приложения. Без него микрофронт отвалится. 
- singleton – указывает, разрешено ли иметь более одного инстанса модуля в окне 
- requiredVersion – сравнение версии инстанса модуля в окне. При одинаковых модулях, но разных версиях отдается предпочтение более свежему. 
В целом, мой конфиг для дочернего приложения выглядит так:
const { ModuleFederationPlugin } = require('webpack').container;
const deps = require('../package.json').dependencies;
const { moduleName, entrypoint } = require('../src/static/app-manifest.json');
module.exports = function (isProduction) {
  return {
    plugins: [
      new ModuleFederationPlugin({
        name: moduleName,
        filename: entrypoint,
        exposes: {
          [`./${moduleName}`]: `./src/${moduleName}`,
        },
        shared: {
          react: {
            requiredVersion: deps.react,
            eager: !isProduction,
            singleton: !isProduction
          },
          axios: {
            requiredVersion: deps.axios,
            eager: !isProduction,
            singleton: !isProduction
          },
          mobx: {
            requiredVersion: deps.mobx,
            eager: !isProduction,
            singleton: !isProduction
          },
        },
      }),
    ],
  };
};От конфига хоста он отличается лишь наличием флага isProduction и в таком виде его легко тиражировать по другим приложениям.
Однако по неизвестной причине не все модули шарятся. Некоторые крашат приложение. Другие могу некорректно инстанцироваться или грузятся целиком. Например, у нас только в одном приложении есть мигрирующий баг, когда не инстанцируется i18n и из-за этого не подтягивается локализация, при этом, перезагрузив страницу, проблема пропадает. Странно то, что все приложения имеют одинаковый конфиг и точку входа, различия только в нейминге некоторых несущественных элементов. Ответ на это может быть утверждение Вадима Малютина из его доклада для HolyJS. Я же данную проблему не решил и просто отключил потребление модуля для данного приложения.
Другая проблема – поддержание актуального состояния пакетов. Т.к. у нас UI kit поставляется заказчиком, возникают некоторые проблемы с обновлением. Так, например, т.к. потребитель у нас дочернее приложение, бывало часто, что если версия библиотеки не совпадала с хостом, то у нас отваливались почти все стили, т.к. в классах менялись хеши.
Еще одна проблема – плохая подготовка библиотек. Не хочется говорить об этом открыто, но стоит отметить, что при неправильной организации библиотеки она может вывалиться в remoteEntry целиком и полностью вместо того, чтобы упасть в свой чанк. И тут вы можете потерять еще одно преимущество – вместо того чтобы тянуть по сети небольшой файл, вы тянете огромный чанк. Так, например, при переходе на Module Federation мною было замечена уменьшение траффика на дочернее приложение с 500 на 40кб в ранних версиях (к сожалению, скриншоты потерял, придется верить на слово и не только мне), но однажды ситуация изменилась в худшую сторону.
Микроинфаркт №5. Code splitting
И, наверное, последняя проблема, с которой я столкнулся – разбивка кода на чанки. Так, на очередном цикле работы, я решил заняться оптимизацией приложения и под нож у меня попал babel, т.к. не давал адекватно протестировать приложение в условиях плохого соединения. «Скачивание» 20мб девелопрских ассетов по 3g как раз хватит выпить пару кружек кофе и поэтому на его место пришел esbuild, который параллельно вытеснил собой и Terser. Но, прописав ручные чанки все дочерние приложения упали с ошибкой. Я грешил на esbuild, но оказалось, что Module Federation не дружит с такой оптимизацией, т.к. сплитит самостоятельно. Решилась ли эта проблема на сегодняшний день я не знаю.
Вместо выводов
Обычно, в конце статьи делаются какие-либо выводы о технологии и т.д. Я не хочу повторяться о том, насколько крут Module Federation, я не скажу ничего нового. Он действительно настолько хорош, как о нем говорят.
Скорее, я дам самому себе несколько советов, если придется работать с Module Federation, и не только:
- Пересмотреть способ организации работы со стейтами. Сейчас у нас все очень похоже на dependency injection, но как-то криво, на мой взгляд. Если двигаться по этому пути, то опробовать, например, Inversify. Если посмотреть под другим углом, то попробовать событийно-ориентированный стейт-менеджер. При поиске я наткнулся на Storeon, выглядит интересно, но никаких демок я не делал. Или же вообще общение между микрофронтами вынести в worker, хотя на первый взгляд выглядит как оверхед, но в пет проекте есть нечто подобное. 
- Подготовить shared-библиотеки. И не одну. И сразу. Дело в том, что, работая над микрофронтами, все-равно что-то может повторяться в дочерних приложениях и лучше сразу уносить это в одну точку, т.к. в начале проекта мы не задумывались ни о переиспользовании логики, ни о переиспользовании компонентов, не смотря на ui kit. И так же стоит учесть, что лучше отделить логику от ui, потому что можно столкнуться с неожиданным поведением, напимер, «отвалы» контекстов, на которые многие жалуются, но с таким я не сталкивался. И в целом, лично мне нравится подход dumb components, не раз себя оправдывал. 
- Абстракции. Как только появилась мысль сделать абстракцию – надо её делать, а не откладывать на потом. Естественно, в пределах разумного. К сожалению, я сначала думал отделаться «малой» кровью, пришлось писать сразу 3 и быстро их интегрировать. 
- Оптимизация приложения. Да, преждевременная оптимизация – плохо. Но тогда не будет сюрпризов, например, с чанками, которые постигли меня. Необходимо даже на промежуточных этапах гонять бенчмарки и по возможности оптимизировать то, что есть. Особенно Core Web Vitals, потому что проход напрямую в точку, где происходит монтирования микрофронта может стать очень долгой операцией, и, если вовремя не отследив просадку производительности, можно получить ситуацию необходимости очень трудоемкого рефактора. Сетевые метрики тоже еще никто не отменял. 
- Делать приложения абсолютно независимыми. Module Federation прекрасно позволяет это сделать - разрабатывать и использовать приложения отдельно и независимо очень круто! Но тут вырастают накладные расходы на Developer Experience, т.к. у меня была ситуация с dead code в продакшн сборке, и, каюсь, не везде удалось его убрать в силу разных причин. Так же, могут вырасти расходы на CI/CD и инфрастуктуру, но мы обошлись простым деплоем каждого приложения отдельно через Jenkins. 
- Тесты. Просто потому, что было прямое указание. Мы тесты не писали. Как оказалось в последствии, очень зря и я очень жалею, что и тут я думал, что «пронесет». 
- Репозитории. Следить за 11 репозиториями фронта в какой-то момент становится очень сложно. Что с этим делать - пока не ясно, но взгляд устремляется в сторону монорепозитория. 
На этом у меня все, всем спасибо за внимание и успехов!
Комментарии (21)
 - marshinov08.02.2022 23:04- приложение на любом стеке и "вклинить" его в существующую систему - Мухаха, оно конечно "вклинивается", но без single spa роуты делать больно:) - Если я не ошибаюсь, feature modules предполагает нахождение на одном сервере, а module federation позволяет тянуть части системы из любого места - Я никогда не пробовал, но, кажется, что можно разные чанки раскидать по серверам, но зачем... Если вы не про деплой в прод, а про репозиторий, то в одном репо, да. 
 - movl09.02.2022 00:20- Смотрели ли на NX, и если да, то почему выбрали webpack module federation?  - skeevy Автор09.02.2022 10:05- начал смотреть на NX, но слишком поздно, под конец проекта. На другом проекте обкатывают коллеги лерну и она им больше не нравится, чем нравится. Думаю, NX будет следующим. Но это история не про module federation 
 Сам module federation выбрал по нескольким причинам:
 1) Шаринг зависимостей. Не нужно писать костыли для определения инстансов бибилиотек.
 2) Подкупили утверждения автора технологии по поводу экономии сетевого трафика и это на самом деле оказалось правдой
 3) По сути, конфигурация простая, но выглядит заковыристо. Пару строк в конфиг вебпака, бутстрап для энтиропоинта - и микрофронтенды готовы к работе
 4) Я слишком буквально воспринял фразу "подключить любое приложение в любой момент". Никто другой не мог на тот момент предложить, что можно встроить без костылей и лишних библиотек/фреймоврков механизм работы с приложениями. Да, было что-то уже в вебпаке плагинчик (не помню как называется), который позволял делать схожее, но причина ниже. Я ориентировался на то, что завтра/полгода/год с бухты-барахты заказчик притащит команду ангулярщиков, а мы все пишем на реакте (реакт был в требованиях тз). И нам как-то придется всем месте жить, а бизнес слышит про микрофронты и думает, что все просто.
 5) У меня была абсолютная свобода действий. Я люблю работать с новыми библиотеками, и тут подвернулся такой шанс. Хотя, возможно, сейчас бы я не стал так рисковать как год назад. А тогда я увидел новую хайповую фичу и решил попробовать.
 Да и возможно выбор module federation был yolo-решением и, слава богу, оно сыграло и опрадалось. Но, опять же, впредь я вряд-ли рисковать буду таким образом - movl09.02.2022 12:51+2- Мы в итоге пришли к NX. Изначально на основном проекте была своя система сборки модулей, на основе вебпака. Потом сделали свои плагины на основе DllPlugin от вебпака, чтобы части приложения можно было подключать через манифесты, в то время module federation еще пока не было. Это позволило перейти в монорепозиторий на лерне, и в дальнейшем на сборку ангуляром с кастомными скриптами под вебпак. Сейчас собираемся перейти на NX, так как в других проектах он себя хорошо показывает. Я правда не знаю, на сколько хорошо NX интегрируется с проектами на реакте, но с ангуляром снимает очень много головной боли. - Я ориентировался на то, что завтра/полгода/год с бухты-барахты заказчик притащит команду ангулярщиков, а мы все пишем на реакте - В этом плане обычно возникает больше проблем с когерентностью, чем со сборкой, чтобы зацепить различный роутинг, туже авторизацию и т. д., но я так понял вы и сами с этим частично столкнулись. Лично для себя, я пришел к выводу, что такие вещи надо закладывать заранее, но по возможности стараться делать приложение на одном стеке. Сейчас в нашем приложении это не так, и по итогу куча самописного кода под какие-то корневые механизмы. - В целом было достаточно интересно почитать про ваш опыт. Спасибо. 
 
 
 - skeevy Автор09.02.2022 13:06- Сейчас собираемся перейти на NX, так как в других проектах он себя хорошо показывает - Я видел, что NX не поддерживает отдельные релизы подсистем, это дейтсвительно так и насколько больнно делать свои workaround'ы для этого? 
 У нас каждый фронт релизится отдельно, интересно попробовать спроецировать этот опыт на будущее и подготовиться :)- я так понял вы и сами с этим частично столкнулись - Да, но не сказал бы, что сильно было критично. Самая большая проблема с шарингом состояния и передачей из дочери в ядро. Например, пагинация у нас в шапке ядра, еще и хитровыдуманная, поэтому пришел к выводу, что нужно делать DI и выводить методы в стейт ядра, чтобы дочки их дергали. Отсюда и думаю, что в следующий раз попробовать общаться через воркеры, оценить затраты и плюсы/минусы 
 Спасибо за ваш отзыв!
 - LFFATE09.02.2022 22:58+1- Мне не понравилась федерализация. Топорно, сложно, тяжело типизировать. Если нет требования поддержки старых браузеров, проще построить расширения на базе обычных esm. Гибкости больше. И контроля.  - skeevy Автор09.02.2022 23:03- А с чем конкретно возникла сложность в типизации? У нас были проблемы в типизации бутстрапа (устали костылить и влепили мужицкий ts-ignore) и точку входа в дочь, если меняется стор ядра (приходится генерировать .d.ts и перекладывать руками в common), а так в остальном проблем не было  - LFFATE11.02.2022 11:05- дык, при потреблении федерализации откуда типы брать? насколько помню, официальный ответ на гитхабе был в духе "нет совместимости с тайпскриптом". Ну и нет совместимости у федерализации с остальными сборщиками. Что привязывает консьюмеров к вебпаку. Хотя нормального экспорта в esm у вебпака по-моему до сих пор нет. Активно тестят и пишут в соответствующий ишью на гх, слежу в полглаза, но кажется, всё ещё не для прода. - Ну и в целом мне кажется устаревшим подход вебпака к постоению зависимостей. Например, все модули лежат по номерными ключами в глобальном объекте. Не знаю, как в пятой версии, а в четвёрке была проблема с двумя фронтами на одной странице - вебпак одного затирал объект зависимостей другого. - В общем, полно там проблем. Часть из них легаси, часть из них вызвано тем, что вебпак не умеет в esm. а нативные модули уже давно поддерживаются везде + работают из коробки. - Ну и возвращаясь к типам - чтобы консьюмить модули с типами, генерю для каждого модуля d.ts и кладу его в кастомную папку с типами, которая работает как node_modules, импортирую модули как обычные модули из node_modules, в мапингах зависимостей коллбек в духе "если модуль начинается с project-name-*, то рерайтим импорт "вот так". Где "вот так" - динамический импорт esm. Да, он возвращает промис, то top level await тоже уже давно не диковинка.  - skeevy Автор11.02.2022 11:32- Ну и нет совместимости у федерализации с остальными сборщиками. Что привязывает консьюмеров к вебпаку. - а должна быть? Сборщик запилил такую вещь и логично, что завязывает на себя, чтобы пополнить комьюнити. Почему это не делают другие - вопрос. Хотя, судя по настроениям - не вопрос, ведь большинству либо страшно браться, либо "фу-фу, нафиг надо" . 
 Для сборки приложенек - вебпак, для сборки либ - роллап. Для меня ну вот вообще не проблема привязки к сборщику. Можно, конечно, приплести сюда snowpack, vite и все остальное, но для меня скорости стало достаточно, отказавшись от babel в пользу esbuild, а если надо будет собрать все лучшее - там где-то еще должен жить gulp, можно велосипед из сборщиков вокруг него построить, только зачем?- дык, при потреблении федерализации откуда типы брать? - я уже выше писал, что из коммон либы я в своем случае складывал. Неудобно, но не смертельно, либо подцепить кастомную types в tsconfig (что, видимо, вы и сделали). - Например, все модули лежат по номерными ключами в глобальном объекте. Не знаю, как в пятой версии - Лежат точно так же в объекте, но не глобальном, если не указывать scope default. Каждый микрофронт может искать в отдельном скопе себе зависимости и выбрасывать туда, если нет зависимостей 
 У каждого выбора есть свои сильные и слабые стороны. В случае моем, все сильные стороны перекрыли слабые. И я в целом остался доволен, а предупредить про неприятные моменты - вот цель статьи, потому что нигде это не освещается практически
 
 
 
 - uyrij09.02.2022 23:53- В чем была проблема хешей для имён в JS/CSS ? Это webpack или любой сборщик автоматом же должны уметь в билде?  - skeevy Автор10.02.2022 00:06- Нет, просто в хост приложении загружается uikit и шарится в микрофронт. Сответственно, инжектятся стили с хешами версии ядра. 
 В микрофронте приложении uikit потребляется из хоста, но если версия будет, например, младше хоста и меняли, допустим, инпут или таблицу - стили отлетали, т.к. в дочернем приложении ожидаются другие хеши для css классов (использовались scss modules). Это как раз случай, когда, вероятно, использовать singleton для библиотеки не лучшее решение, но у нас uikit непонятным образом весит больше 2мб (точнее понятным - некоторую графику загнали в base64 в css и еще куча других проблем) и это мрак полный. Пришлось смириться и быть внимательным, чтобы обновлять единомоментно
 Проблема тут еще в том, что uikit нам поставляли со стороны и информациооная поддержка была не лучшего качества - очень долго выбивали ченджлоги, в итоге пришли к тому, переодически высалаются PDF (!!!!) с описанием изменений, про сторибук молчу, больше выглядел как лишняя примочка не понятно для кого - uyrij10.02.2022 06:44- Понятно. Иногда в девтулз посмотришь, а там реакт модульный, и ещё Vue, и ещё ???? jQuery сбоку и все от известного бренда приложение рабочее. - У вас реальный проект. ???? 
 
 
 - aderbin10.02.2022 15:23+1- У заказчика есть MVP, необходимо «просто его доработать» (с) - Тоже работаю в Лиге цифровой экономики, знаю некоторых заказчиков и проекты - очень долго, громко и от души смеялся, когда прочитал :)  - skeevy Автор10.02.2022 15:25- К сожалению, такое случается :) 
 Когда заказчик узнал, что от MVP ничего не осталось, его удивлению не было предела :)
 
 
           
 
marshinov
А в итоге зачем на проекте требовались микрофронтенды?
skeevy Автор
Я всей ситуации не обладаю и не участвовал в проектирований всей системы, мне донесли как данность. Да и если бы хотел, всего рассказать не могу, сами понимаете. Но, постараюсь ответить, исходя из того, что получается в итоге.
Микрофроненды нашли хорошее применение в организации ролевого доступ к АРМ. Как я говорил в статье, у каждого приложения есть манифест и сервер о них знает. В зависимости от привелегий пользака, север формирует пул манифестов и отправляет его клиенту. Не обладая нужными правами, пользак при всем своем желании не попадет туда, куда не следует, просто потому, что ему этот микрофронт не доступен с домашней страницы. Конечно, он может попытаться по прямой ссылке пойти, но и там его ждет облом, но это уже немного другое
Целевая аудитория - системные администраторы, и у них есть разные уровни доступа. По требованиям ТЗ предполагается, что могут быть как локальные админы (администраторы структурной единицы в предприятия), так и супер админы (админ всего предприятия/нескольких предприятий, хоть всей РФ). Одни должны настраивать пул доменов, NTP, DNS и т.д., другим же достаточно предоставить доступ к управлению машинами, пользователям, принтерам.
При этом, объем системы большой и изменение в функционале точечно затрагивают модули, снижая время на CI/CD и вывод в релиз отдельных элементов системы или выноса функционала в отдельный домен.
К сожалению, были моменты корректировки ТЗ и на одной из крупных подсистем было очень много стихийных изменений, и мы бы уперлись в конфликты в репозитории и ожидании развертывания без микрофронтов, dev-стенд вообще по несколько раз в час обновлялся.
Так же, сильно ускорилась работа, были сформированы несколько команд/одиночных разработчиков, работающих абсолютно независимо друг от друга, без ожиданий очередей сборки с минимальными конфликтами в git
Более конкретно рассказать не могу, чтобы не получить по голове за разглашение :)
Надеюсь, ответил на Ваш вопрос, если нет, то уточните, где я свернул не туда
marshinov
Ну здесь можно и клеймами в JWT решить. Если к беку доступа нет, то и фронтовый никакого доступа не раскроет, а бек в любом случае придется защищать.
Вот тут сборка - да, а все остальное через feature modules можно решить.
skeevy Автор
Вы совершенно правы, но, как говорится, кто платит - тот и музыку заказывает :)
Заказчик в будущем своими силами хочет расширять функционал системы и не хочет копаться в фронтовых делах. Ведь на самом деле дествительно легко поднять любое приложение на любом стеке и "вклинить" его в существующую систему, чем копаться в архитектуре и т.д., тем более, в какой-то момент это станет легаси и бизнес не захочет слышать просьбы на выделение средств на рефактор :) Но, это уже совсем другая история
Если я не ошибаюсь, feature modules предполагает нахождение на одном сервере, а module federation позволяет тянуть части системы из любого места. Поправьте, если не прав.