Pull to refresh

Микрофронтенд, как не скатиться в ад

Reading time8 min
Views6.9K

Всем доброго времени суток!

Сегодня речь пойдёт о таком страшном звере, как micro-frontend. Знаю: всем эта тема порядком надоела, но просмотрев полтора десятка выступлений осознал, что не все до конца понимают, что это такое и какие сложности следует решать при организации micro-frontend’а. В данной статье я дам универсальные советы, расскажу с чем не стоит связываться и, в целом, как не превратить проект в ад из callback’ов или непонятных интерфейсов. Итак, обо всем по порядку.

Что такое micro-frontend?

Точного определения днём с огнём не сыщешь. Суть в том, что термин micro-frontend подразумевает наличие множества изолированных приложений с интерфейсом, для взаимодействия с ними посредством API. Это позволяет использовать версионированность, не опираясь на рядом стоящие компоненты. Наглядным примером такой реализации являются различные npm-пакеты. Так же micro-frontend подразумевает под собой использование микро-сервисной архитектуры, что в совокупности даёт нам инкапсулированную логику не зависящую от окружения.

Чем был плох предыдущий подход - монолит?

Для того, чтобы понять преимущества micro-frontend’а нам следует разобраться чем именно он отличается от, так называемого, монолита.

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

Я прямо слышу крики: “ Что за ересь?!”. Давайте разберемся поподробнее, что же я имею в виду. Для начала задам пару наводящих вопросов для определения говорим ли мы об одном и том же.

  • Можно ли взять какой-то модуль и использовать его в другой системе, при этом не занимаясь его адаптацией?

  • Этот модуль зависит от экосистемы (стека) окружающего его приложения?

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

Плюсы micro-frontend’а

Теперь разберём, что нам дает использование micro-frontend’а и в каких ситуациях его следует применять. Для начала предлагаю определиться для каких проектов он актуален: на мой взгляд, это проекты выше среднего. В таких проектах, как правило, более одной команды и более десяти разработчиков frontend’а. Цифры условные, но наглядные. Если с размером все понятно, то предлагаю перейти к плюсам, которыми нас одаривает micro-frontend.

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

  • Версионность - преимущество двоякое и мы еще вернёмся к нему в минусах. Если и говорить об этом как о преимуществе, то оно позволяет точно знать с какой версией модуля мы работаем на проекте в данный момент времени и как им управлять.

  • Инкапсулируемость – не путайте с модульностью. Да, модули тоже могут быть зависимыми, но инкапсулируемость дает нам изолируемость всей логики в модули, которая не зависит от внешних факторов.

  • API - так как вся логика приложения у нас инкапсулирована, а нам как-то надо  связываться с приложением, то для управления используют API. Оно отвечает за обмен данными с модулем, а также его состоянием.

  • Документация - без документации micro-frontend вообще невозможен. Как было сказано выше, вся логика инкапсулирована в модуль, а управление данными, состояниями и прочим происходит только при помощи API. Выходит, что без документации или хотя бы типизации мы потратим уйму времени разбираясь как управлять нашим фронтом.

  • Тесты - тесты обязательный атрибут micro-frontend’а. Они позволяют контролировать не только качество работы, но и в целом работоспособность данного модуля. 

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

  • Масштабируемость команды – как известно, мы работаем для бизнеса. Иногда у этого самого бизнеса возникает потребность ускориться в разработке, и тогда приходят с вопросом «как это сделать?». Очевидно, потребуются люди, их организация, а также обеспечение сотрудников загрузкой и отслеживание производительности. Модульная система как раз позволяет каждой команде спокойно работать над частью своего кода и, при этом, не мешать соседу.

  • Масштабируемость приложения - так как у нас все состоит из кирпичиков, то присутствует возможность построить стену необходимой длины.

  • Скорость деплоя - поскольку все построено на модулях, не зависящих друг от друга, и их размер гораздо меньше размера готового приложения, то деплой можно запустить в несколько потоков (по отдельным модулям). Некоторые модули могут переиспользоваться не один раз, что также предоставит профит, не требующий дополнительных комментариев.

  • Релиз частями - несколько сомнительное преимущество, но тем не менее позволяет отправлять в релиз части системы по отдельности. Удобно, когда много команд и у всех плавающие спринты и производительность.

Как видите у micro-frontend’а полно плюсов, хотя это как в медицине: чем больше плюсов, тем больше побочных эффектов. Для полноты картины о них надо знать и понимать, а потому переходим к минусам.

Минусы micro-frontend’а

Как известно, технологий без минусов не бывает. Точнее бывает, но только в России. Micro-frontend это не обошло стороной: минусов много, и они достаточно весомые, о чем я и расскажу ниже. С частью я знаю, как бороться, а с частью, к сожалению, нет.

  • Архитектура - модули должны содержать в себе инкапсулированную логику. Это делает планирование не совсем тривиальной задачей, что в свою очередь повышает трудозатраты на разработку.

  • Тестирование – тестировать придется всё и вся. Кроме обычных тестов потребуются еще интеграционные, так как связь между модулями осуществляется исключительно по API.

  • Версионность – вот теперь давайте поговорим об этом, как о минусе. Вам придется точно понимать и отслеживать, что и в какой версии сделано. Это значит, что потребуется карта зависимостей, которая будет с завидной регулярностью стрелять вам в ногу.

  • Сборка релиза - еще одна головная боль, приводящая в ярость релиз-менеджеров и заставляющая приносить жертвы в полнолуние, так как  постоянно приходиться сверять версии модулей,  которые  требуются в сборке, а также их  зависимости.   

  • Документация - держите её в актуальном состоянии постоянно, ведь от нее зависят соседние команды. Я серьёзно. Упаси вас Бог что-то сделать и не задокументировать это - вас сожгут, как еретика, при первом же релизе сторонней команды.

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

  • Производительность - может я для кого-то сейчас открою тайну, но скорость быстродействия micro-frontend’а, как правило ниже, чем у монолита. Это связано с тем, что не всегда понятно что можно кэшировать, а что категорически нельзя. Следует грамотно выбирать стратегию кэширования и обновлений, так как браузер тоже будет подкидывать дровишек в ваш, и без того не маленький, костер пригорания. Плюс ко всему объемы перегоняемых данных из одного модуля в другой, гораздо выше. 

  • Избыточность - каждый из модулей должен содержать в себе всё, что ему необходимо для работы. Да, абсолютно всё равно, что в соседнем модуле есть точно тоже самое. Micro-frontend должен быть атомарным и мочь функционировать в гордом одиночестве.

  • SEO - вишенка на торте. Мы же ещё помним о том, что мы работаем на бизнес, а залог успеха бизнеса — это продвижение? Соответственно следует продумать как именно у вас будет работать SSR (Server Side Rendering - он же серверный рендеринг страниц для уменьшения нагрузки на браузер), как проставлять теги и многое другое. То самое, за что вас будут парафинить ваши коллеги, занимающиеся этим самым продвижением.

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

Путь наверх

Как поется в одной песне “Не пройдя преисподней, Вам не выстроить рай!”. Ещё до начала работ вам следует решить все организационные вопросы, спланировать кто, чем будет заниматься и в какой последовательности. Проще говоря, Вам нужна дорожная карта хотя бы на полгода.

  • Обеспечить работу всех в одном репозитории - вы не ослышались. Лучшее что вы можете сделать - использовать монорепозиторий. Уже вижу летящие в меня камни, но предлагаю не торопиться с выводами.

Для облегчения вашей участи есть прекрасный инструмент - NX (https://nx.dev/). Он позволяет разбить монорепозиторий на библиотеки, согласно тем модулям, которые будут содержаться в готовом приложении. Также NX позволяет ускорить локальную пересборку проекта, за счёт инкрементального обновления, вести версионированние, и при необходимости генерировать npm-пакеты с нужными зависимостями. Инструмент содержит в себе storybook, который будет просто необходим для библиотеки компонентов и тестирования готового результата. Доставив плагины, вы всегда сможете посмотреть, как реагирует модуль в связке или в вакууме, а во избежание циркулярных зависимостей воспользуйтесь функцией построения графиков.

  • Микросервисы - полноценный micro-frontend не может существовать без микросервисной архитектуры. Чтобы облегчить её создание, предлагаю использовать Nest (https://nestjs.com/), как принято про него говорить: Express на максималках. Вам так или иначе придется создавать слой абстракции (BFF - он же Back for Front), чтобы модули ходили через него на бек. Nest позволяет стандартизировать все запросы к беку, а также настроить кастомную генерацию ошибок. Nest умеет нормально обрабатывать DTO, которые потом спокойно съедает swagger, которые вы сможете прикрепить к storybook, что даст вам почти идеальную документацию для работы с модулями.

  • Настройка окружения - под этим я подразумеваю настройку линтера, внедрения TS, настройку прикомитных хуков. Причем прикомитные куки должны быть настроены таким образом, чтобы они запрещали вообще комит, если ругается линтер, или в какой-то момент не проходят тесты. Это убережет вас от говно-кода, а также позволит следить за качеством кода в целом.

  • Качество кода - для поддержания качества кода вам потребуется какой-либо анализатор кода. Рекомендую использовать Sonar (https://www.sonarqube.org/). Данный инструмент бесплатен, а также имеет готовые плагины под все популярные IDE. Sonar умеет определять дубляж кода, давать рекомендации по упрощению алгоритмов и много чего еще, что позволит хоть как-то разгрузить и без того забитую голову. Его тоже можно включить на прогон прекомитов.

  • Отслеживание нежданчиков - Я думаю все в курсе, что иногда на фронте бывают такие юзер-кейсы, которые не придут ни одному разработчику или тестировщику в трезвом уме и здравой памяти в голову. Для таких случаев рекомендую внедрить в проект Sentry (https://sentry.io/). Он позволяет отслеживать действия пользователей, приведших к ошибкам, фиксировать их или показывать с каких устройств пользователи осуществляют вход. Так же в нем достаточно много всяких метрик, на которые вы можете положиться. Метрики разные: начиная от производительности и заканчивая статистикой разного рода ошибок. 

  • HTTP2 - без этого тоже не получится обойтись, поскольку наличие HTTP2 позволит увеличить скорость загрузки ваших файлов и увеличить количество потоков для их загрузки.

  • Gzip - включение данной технологии позволит увеличить скорость загрузки и уменьшить объем пересылаемых данных.

  • Сервер объектного хранения - данный сервер позволит вам хранить картинки, документы и много чего еще не в репозитории, а на отдельном сервере, который может масштабироваться как вашей душе угодно. Я рекомендую использовать MinIO (https://min.io/). Он позволяет хранить временные файлы и автоматически их удалять по таймеру, отдавать в множество потоков статику и вообще он красавчег. 

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

Вывод

Как уже не раз говорил: сначала думаем, потом делаем. Довольно редко я встречал приложения с чистым micro-frontend’ом. Чаще всего используется разного рода гибриды, которые зависят от стека и потребностей конкретного проекта. Не могу сказать, что micro-frontend это панацея и его точно не стоит затягивать во все проекты подряд. Не всегда монолит плох, как это стараются преподнести в свете последних тенденций. Он хорош тогда, когда у вас много команд и проект сложнее среднего. Помните, что вам работать с тем монстром, которого вы породите и постарайтесь сделать так, чтобы вам не было за него стыдно, когда вы уйдете с проекта.

P.S.

Я с радостью подискутирую на данную тему со всеми желающими, а также готов поделиться своим опытом и знаниями в приготовлении micro-frontend’а. Статья получилась объемной и всех нюансов просто не упомнишь. С радостью отвечу на любые вопросы.

Only registered users can participate in poll. Log in, please.
Вы готовы обмазываться micro-frontend?
32.53% ДА, я на все готов(а)27
33.73% Я подумаю над вашем предложением28
33.73% Ваш план говно, я брезгаю28
83 users voted. 17 users abstained.
Tags:
Hubs:
0
Comments19

Articles