В этой статье я рассказываю, как мне удалось сделать весьма не плохую архитектурное решение с применением Microfrontend и Feature Sliced Design. Вкратце что из себя представляет обе эти архитектуры.
Microfrontend - пришедшее из мира микросервисов, где каждый сервис условно работает автономно и имеет не сильную связь с другими сервисами. Микрофронтенд применяется что-то из этого рода архитектур, где контейнер (App) условно разбит на несколько модулей, и каждый модуль может быть написан на разных фреймворков и быть подключен к единому контейнеру.
Feature Sliced Design (FSD) - достаточно новая архитектура я считаю, но ее преимущество в том эта разбиение файлов на отдельные слои где каждый слой не может быть зависим от других слоев, этих слоев не так много и их довольно легко запомнить (app, pages, widgets, features, entities, shared). Эта модель позволяет спроектировать интерфейс как композицию различных компонентов, не связанных напрямую друг с другом, и, тем самым, добиться низкой связанности компонентов интерфейса.
Почему же стоит задуматься над решением применить их обе в проекте, ведь ничего нам не мешает их использовать в слиянии, микрофронтенд не требует дополнительных настроек на сервере, ведь все развертывается и запускается в одном проекте, а FSD имеет достаточно удобную структуру файлов, применение этих двух архитектур будет must-have'ом для проекта с высокой нагрузкой, если конечно вы не пишите проект с простеньким функционалом.
Принципы микрофронтенда и FSD
Разделение по функциональности
Автономность
Слабая связь
Гибкость и легкая масштабируемость
Границы контекста
Высокая атомарность
Границы контекста

Для примера я разделил проект на 2 модуля кроме основного контейнера, в будущем можно будет расширить проект до нужных вам модулей. Для инициализации модуля используется пакет create-mf-app.
/container
- наше приложение, куда пользователь будет попадать, из себя он будет представлять довольно типичную структуру для React App, но в дальнейшем мы расширим ее файловую структуру.
/service-api
- модуль API
, тут будут раскиданы работы с интерфейсами, в себе он будет иметь один пакет работа с запросами.
/service-shared-components
- модуль для shared компонентов или uikit
Первичная инициализация:
npx create-mf-app
Вам предложат выборочную установку:

Application - приложение, тем самым вы создаете модуль с исходным фреймворком который вы укажите из пакета, в моем случае эта React.

После всех этих манипуляций, связь между модулем обеспечивает пакет и webpack'а ModuleFeredationPlugin
. В конструктор он принимает объект, разберем что он может из себя представлять.

name
- имя модуля.
filename
- удаленный entry файл куда будет размещен наш код при запуске модуля.
remotes
- подключение удаленных модулей, обычно он указывается домашним приложением, заметьте что для обращение я использую @
, чтобы typescript не ругался. для подключение указываются префикс имени модуля и путь по которому он будет запущен.
exposes
- инициализация или путь модуля для развертывания домашним приложением.
shared
- инициализация зависимости пакетов, дабы избежать перелинкования версий зависимостей.
"@uikit": "uikit@http://localhost:8081/remoteEntry.js",
"@api": "api@http://localhost:8082/remoteEntry.js",
После перезапуска модуля вы увидите следующую картину:

Этот файл удаленной записи, remoteEntry.js
, представляет собой файл манифеста всех модулей, которые предоставляются приложением.
После того как подключили все модули к единому контейнеру, можно будет рассмотреть вариант расширить файловую структуру.

features - эта фичи, которые явно работают по определенной бизнес логики, там будут происходить разные манипуляции с запросами, работа со стором.
widgets - самостоятельный интерфейс, который присущен бизнесу в себе он может включать разные фичи, сущности и shared компоненты.
Заметьте что у меня отсутствует слой entity, так как его я буду брать из сервиса service-api
.
@service-api/posts.api

в service-api
имеется интерфейс для получение постов, в качестве теста я взял за основу jsonplaceholder.
@container/features/posts/getPosts

В домашнем приложение я инициализирую usecase, который будет возвращать мне список PostEntity, в данном случае я просто использую интерфейс postsApi, так же вы можете работать со стором делать разные манипуляции с селекторами.
@container/App.tsx

в файле App.tsx инициализируется наша фича и виджет PostCard, делается первичный запрос на получение постов с последующим сохранением и отображением.
Заключение
В этой статье мы рассмотрели концепцию микрофронтендов на примерах, обсудив их преимущества перед монолитными фронтенд‑приложениями и другими доступными настройками. Микрофронтенды предлагают отличные функции и просты в использовании.
С помощью create‑mf‑app мы реализовали архитектуру микроинтерфейса так же легко, как и с помощью приложения Create React. Лично мне нравится стиль микроинтерфейса, потому что его легко поддерживать в командах. Кроме того, создание внешнего интерфейса и безопасность управляются довольно элегантно.
Надеюсь, вам понравилась эта статья, и не забудьте оставить комментарий, если у вас есть какие‑либо вопросы. Удачного кодирования!