Comments 12
Спасибо за статью.
Плюсы/минусы подхода есть?
Как ведет себя структура кода и его размер в более сложных приложениях, чем пример из статьи?
Где микрофронтенд будет плох и будет ииеть оверхэд?
mfe хороши, но не панацея. При использовании mfe сразу встаёт несколько вопросов:
1) Как поддерживать консистентность зависимостей? Для себя принял, что mfe хорошо дружат с nx. При использовании nx сразу упрощается управление зависимостями, деплой, запуск в dev режиме(запуск был актуальным вопросом т.к. количество mfe в проекте было более 20).
2) Шаринг зависимостей. Тут всё очень неоднозначно т.к. при шаринге какой-либо библиотеки мы сразу теряем treeshaking т.к. сборщик не может угадать какие части библиотеки понадобятся. Опять же, в данном случае мне помог nx с его упором на создание библиотек из коробки.
3) При работе с большим количеством mfe автоматически встаёт вопрос динамической подгрузки mfe. Если не решить данный вопрос, то вы автоматически будете дёргай тот самый злосчастный remoteEntry.js для каждого mfe.
Также хотел отметить, что автор плохо понимает что получает на выходе. Особенно это хорошо видно в следующем фрагменте:
"@uikit": "uikit@http://localhost:8081/remoteEntry.js",
"@api": "api@http://localhost:8082/remoteEntry.js",
Китовая библиотека компонентов и библиотека для общения с апи не являются самостоятельными единицами. Данные модули должны быть расшарены как общие зависимости через хост приложение.
Про fsd. Подход имеет место быть, но стоит держать в уме, что просто взять и перенести средний/большой проект на fsd не выйдет без специалиста, который хорошо знаком с данным подходом. Сталкивался с ситуацией когда на проекте fsd и всё круто, но в какой-то момент людям приходит понимание, что большая часть разработчиков распихивает код по слоям рандомно и проект превращается в кашу. Поэтому первое время потребуется строгое ревью.
Проблема nx в том что держать микрофронты в одной репе это как купить соковыжималку, но продолжать выжимать фрукты руками) Ведь главная суть микрофронтов в том, чтобы изолировать часть функциональности под какой-то общеизвестной паблик апи, и вынести куда-то отдельно, чтобы эту функциональность могла поддерживать какая-то другая команда со своими процессами. У них это все будет лежать в отдельной репе, а как делать мры, коммиты и так далее - они могут сами решать. Одна монорепа это ограничивает и вставляет палки в колеса - нужно делать как все, подтягивать изменения других команд, вероятно еще запускать ненужные микрофронты (если не удосужились нормально настроить запуск, что чаще всего и случится)
У монорепы есть минусы- не спорю с этим.
Никто не мешает оставлять микрофронты в монорепе обособленными.
Плохо настроен запуск? Тут же вопрос скорее к людям.
Монорепа заставляет работать однотипно? А всегда ли это плохо?
В общем,сколько людей,столько и мнений.
P.S. Да,для микрофронтов идеальный вариант это жизнь в отдельных репах и использовать корректную настройку shared зависимостей,но это не всегда получается(как в вашем примере с запуском).
Тоже добавлю про fsd. Решили его попробовать на текущем среднем проекте - несколько десятков тысяч строк кода.
Плюсы:
Много документации по подходу.
Хорошая идея с разделением на слайсы, сегменты.
Знакомишься со сторонними идеями по улучшению файловой структуры проекта.
Минусы:
В ходе работы возникает путаница, когда разговор заходит о слоях. В архитектурах MV*, Flux и т.д. слоями называется другое.
При разработке возникает много непонятных моментов - какие слои нужны именно в твоем случае (а при избегания кросс-доменности складывается впечатление, что понадобятся все), к какому слою относится тот или иной функционал (у всех вызывает сложность, когда надо определиться, данный модуль это feature или entity? Также возникают сложности с определением, куда поместить такой функционал, как локализация, темизация, переиспользуемые пагинация/сортировка/фильтрация). Все в какой-то степени по-разному понимают FSD, поэтому в команде скорее всего будут частые обсуждение, что и где должно лежать.
Логика страницы вместо того, чтобы находиться рядом в соседних файлах/папках, постоянно размазывается по 3-4 папкам - pages, widgets, features, entities. Это повышает когнитивную нагрузку. Часто приходиться переключаться между далеко расположенными друг от друга папками. На мой взгляд, структурировать проект, беря декомпозицию компонентов за значительную часть основы - это не удачный подход.
Тратиться немало времени на поддержку следования данному подходу. Если бизнесу постоянно нужны фичи и не выделяется достаточно временно на техдолг, то времени заниматься поддержкой FSD в проекте не будет.
Сложно контролировать на code review, т.к. сходу часто не понятно, в какой слой правильней поместить новый модуль.
В следующем проекте вместо слоев FSD, я подумываю использовать примерно следующие:
app - по аналогии с FSD
pages - конкретные страницы и всё (включая конкретные api), относящееся только к конкретной страницы. (вместо постоянного разделения на pages, widgets, features, entities по FSD)
reusable-in-pages - переиспользуемый функционал для нескольких страниц. (вместо widgets, features, entities по FSD)
components - переиспользуемые визуальные компоненты, а также react хуки/улилиты и т.д., относящиеся к этим компонентам.
В двух следующих слоях визуальные компоненты отсутствуют, но компоненты-провайдеры могут присутствовать в 5 слое, т.к. они не визуальные.Хотя возможно 4-ый и 5-ый слои лучше объединить в один, т.к. некоторый функционал (например, toasts) связан с компонентами. А возможно shared стоит использовать как в FSD. Т.е. 4-6 слои из моего комментария сделать одним слоем.
shared-business - переиспользуемый функционал, не относящаяся к конкретным страницам или к какой-либо группе страниц, но привязанная к работе, процессам именно этого приложения. (вместо shared/libs по FSD)
shared-not-business - всё прочее переиспользуемое, не привязанное к приложению, и которое в теории может быть переиспользовано в любом другом проекте. В основном это типы, утилиты, некоторые react-hook-и. (по аналогии с FSD, но без shared/ui и без shared/libs)
Люди слишком много думают, а на деле фсд очень даже простой) Когда делаешь страницу, для начала надо максимально все писать в pages, остальные слои нужны лишь при действительной необходимости, когда нужно использовать какую-то общую функциональность. Например, есть главная страница и страница записей, мы сделали страницу записей и вся ее модель (включая запрос и храние записей) находится в папке данной страницы. Потом добавилась фича, что надо открыть попап с предложением оформить запись (если их нет), и попап этот вылезает на главной. Выносим данные о записях в entities/appointments и можем использовать во всех страницах и фичах. Попап с предложением о записи на самом деле фича, но для начала можно засунуть и в главную страницу по структуре (если мало опыта с фсд). Потенциально просто этот попап может понадобиться и в других местах, и это уже точно должно будет находиться в фичах.
По определению "фича" это какое-то одно бизнес действие, и попап к этому как раз подходит. А "ентити" это какая-то бизнес сущность, используемая чаще всего по всему приложению. Вот например appointment как в примере выше, очень часто там еще находится user. Можно и session положить слегка нарушив методологию касательно кросс импортов (потому что это хоть и не полноценная бизнес сущность, но и не общая не зависимая от проекта штука из shared). Shared слой как раз про общие вещи, которые чаще всего можно скопировать и вставить в другой проект, и при этом они сразу будут работать без каких-то танцев, поскольку это просто независимые компоненты / абстракции / методы. Многие туда кладут session, как я уже говорил считаю это нарушением, так как сессия сильно зависит от конкретной апи.
Вот проблема fsd как раз в том, что есть такие спорные вещи и при этом нет строго принятого пути решения. Например, есть очень частая проблема с так называемыми layouts или templates (каркасы для страниц). Они почти всегда зависят от слоя виджетов, но методология не приветствует кросс импорты в одном слайсе. И выходит что их просто некуда положить по методологии - между страницами и виджетами нет слайсов) Очевидное и простое решение - сделать дополнительный слайс layouts/templates, но тем не менее его все еще не сделали, и идут даже ближе к какому-то computed слою внутри слайса, в котором можно импортировать из других слоев в том же слайсе.
Вот фсд простой как раз когда не стесняешься такие моменты решать, а не пытаешься какими-то костылями адаптировать их под методологию. Ведь если ты долго придумываешь решение, разбираешься как сделать по методологии и так далее, то стороннему человеку придется сделать тот же самый ресерч, чтобы разобраться в твоем решении, когда он его увидит. А методология должна наоборот это упрощать, чтобы новый человек почти сразу же понял что где лежит, и почему такое-то решение принято
Люди слишком много думают, а на деле фсд очень даже простой)
Судя по множеству вопросов и разногласий даже среди senior разрабов в том, что и где должно лежать, фсд на самом деле довольно сложный)
Даже выше в комментах было:
"Подход имеет место быть, но стоит держать в уме, что просто взять и перенести средний/большой проект на fsd не выйдет без специалиста, который хорошо знаком с данным подходом. Сталкивался с ситуацией когда на проекте fsd и всё круто, но в какой-то момент людям приходит понимание, что большая часть разработчиков распихивает код по слоям рандомно и проект превращается в кашу."
Всё это разделение на множество слоев ради переиспользования без кросс импортов скорее приводит не к упрощению, а к усложнению. Плюс функционал, связанный с одной бизнес сущностью, становиться разбросан по нескольким слоям проекта. Думаю, в большинстве проектов было бы эффективней не делить на слои widgets, features, entities, а объединить эти 3 слоя в один слой и разрешить в нем кросс импорты между слайсами.
Я не из веба (из флаттера/андроида), но если я правильно понял, то под fsd вы имеете ввиду использования feature-list вместо layer-list структуры топлевел директорий. Мне кажется, разбиение по фичам гораздо удобнее на больших проектах. Ибо имея 3 папки domain, data, presentation очень сложно одну фичу делать. Опять же, случаи, когда какая-то бизнес-логика шэрится между фичами достаточно редки. Фича - это же не экран. Фича это же не экран, а более общая вещь. Типо настройки - а там много экранов со всяким. Я в случае с фичами делаю папку features/ и уже внутри фичи идёт размазывание по presentation, data, domain и т.д. Ну и есть _common для апи, наигации и прочей общей функциональности.
Про MV* не совсем понял. Это же паттерны презентации, а не архитектура. Эта * - это тоже presentation на уровне архитектуры проекта. В архитектуре всякие presenter, bloc, viewmodel, controller и т.д. выполняют роль презентации. А моделью уже что угодно может быть. Поэтому view и её логика должны рядом находиться. Это всего лишь способы организации логики конкретного виджета
под fsd вы имеете ввиду использования feature-list вместо layer-list структуры топлевел директорий
Под fsd я имею ввиду то же, что и автор статьи - https://feature-sliced.design/ru/
Вы верно подметили про layer-list - что неудобно распределять фичу по топлевел директориям. FSD как раз грешит этим.
Про MV* не совсем понял. Это же паттерны презентации, а не архитектура ...
Я тоже не совсем понял, что именно вы имеете ввиду под архитектурой?) Ок, именно они - не архитектура, а паттерны, используемые для разбиения приложения на слои в многослойной архитектуре.
Но я согласен, что эти слои должны находиться рядом для конкретного виджета/страницы.
Во всех статьях, и фреймворках типа single-spa, предполагаются пошаренные между микрофронтами библиотеки, билд-тулчейн, и даже версия реакта. Как по мне, это нивелирует все плюсы микрофронтов - возможность делать куски приложения отдельными командами независимо. Независимо обновляться, менять стек под свои нужды. Например - накидать какую-нибудь админку, и потом вообще там разработку поставить на паузу. Или наоборот - user-facing часть переписать на next.js. Или, банально, обновлять реакт или библиотеку компонент по частям.
А разделить по фичам приложение на одном стеке - проще через те же чанки вебпака, и eslint-рулы - чтобы зависимости между папками с фичами не плодили.
Вот написал точно то же самое в соседнем треде) Я уверен что микрофронты не нужны, если они не лежат в отдельных изолированных репах. Ведь тогда над ними не удобно будет работать отдельной команде со своими процессами. Думаю микрофронт должен лежать отдельно и предоставлять генерируемую паблик апи для взаимодействия с ним, а детали знать вообще не нужно, и реализация может лежать где угодно, это не должно волновать тех, кто берет этот микрофронт в зависимости
Ну во первых FSD это не архитектура - это методология. Это очень разные вещи. Во вторых какой смысл делать микрофронтенд для инфраструктурных сервисов которые работают с апишками?
Архитектура микрофронтенд с feature sliced design