История о том, как мы на Module Federation съезжали. Часть 1

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Всем привет! На связи Максим Смирнов, архитектор по фронтенду в Тинькофф. В серии статей будет история о том, как мы переписывали один из монолитных сервисов на Federation.

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

О понятиях и монолите

Прежде чем перейти к распилу, давайте договоримся о том, какие слова будем использовать.

сборная солянка с примесью спагетти</p>" data-abbr="Монолит">Монолит — все в одном: бизнес-код, функциональщина, все перемешано. 

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

Module Federation — плагин от Webpack, позволяющий без проблем и костылей стать микрофронтендерами.

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

Любой монолит выглядит примерно так: есть роутинг, компоненты, слои с бизнес-логикой, айпишки, бэкенды. Так выглядел и тот монолит, который мы решили пилить
Любой монолит выглядит примерно так: есть роутинг, компоненты, слои с бизнес-логикой, айпишки, бэкенды. Так выглядел и тот монолит, который мы решили пилить

Роутинг нашего приложения был похож на личные кабинеты у многих компаний:

У роутинга был рутовый slash, определенные страницы, по которым ходил роутинг. Эти страницы имели свою бизнес-логику: где-то показывать графики, где-то — операции, где-то — магазины. Каждая дальнейшая страница имела внутренний роутинг
У роутинга был рутовый slash, определенные страницы, по которым ходил роутинг. Эти страницы имели свою бизнес-логику: где-то показывать графики, где-то — операции, где-то — магазины. Каждая дальнейшая страница имела внутренний роутинг

Мы не рассматривали микрофронтенды, когда думали о распиле. Хотели просто освежить проект — провести небольшой рефакторинг, поменять устаревшие зависимости и прибраться в коде, чтобы все было красиво и на своих местах. Сначала перевели на nx-workspace монорепу, которая у нас в компании стандарт. Даже в одном приложении мы используем nx-workspace, потому что большое количество тулинга для него и из коробки nx-workspace имеет много генераторов, линтеров и команд для запуска тестов и прочее полезное. Потом вынесли в лейзи все, что не было вынесено раньше у монолита. У нас был код, который писали с 2014 года, и его витиеватость зашкаливала. Рефакторинг проводили очень аккуратно, чтобы не сломать в неочевидном месте. Все места, где перемешана бизнес-логика с функциональностью, переписали и вынесли в лейзи-модули.

Мы декомпозировали весь код по библиотекам. Думаю, многие сталкивались со спагетти-кодом, когда в двух разных местах один и тот же код протянут через все приложение идеальным подходом — Ctrl+C, Ctrl+V. Nx позволяет использовать локальные библиотеки, которые можно шарить внутри между приложениями или сервисами. Еще можно перенести в npm-библиотеку, если мы планируем переиспользовать функциональность в других приложениях вне этого репозитория.

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

Самый веселый элемент — это шаринг данных между страницами. Я думаю, многие сталкивались с такой вещью, как state management — ngrx, ngxs, redux. У монолита все описания состояний были в rооte. Мы определили:

По такому чек-листу мы пошли перепиливать и оптимизировать.

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

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

Любой фронт — это монолит. Весь вопрос в том — а что внутри? Внутри спагетти и монолитность или за монолитностью этого бандла скрывается модульность, лейзики, подгрузки. С такими монолитами можно жить.

Сбой — как мотиватор распила

Думаю, многие сталкивались с главной проблемой монолитов: если упал один — упадет всё.

Всего лишь один pull request с дифом на 1000 элементов и одна забытая точка с запятой в нем может убить прод.

Так случилось у нас. Однажды из-за невнимательности на ревью мы пропустили критическую ошибку в коде. Тесты пишут немногие: это же монолит, легаси, вот будут микросервисы — будут и тесты. Проверку на стенде тоже не проводили: были уверены в своем коде, ну как это бывает — задача-то горит! А так как у нас монолит, сделав ошибку в одном модуле, мы получили полностью лежащее приложение. Такое никому не нравится. Поэтому мотиватором распила и перехода в микрофронты стали сбои — их было много. 

Сбой в монолите — это:

Сбой в микросервисе — это:

Вместо заключения

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

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

Источник: https://habr.com/ru/company/tinkoff/blog/718302/


Интересные статьи

Интересные статьи

Это был типичный подмосковный ЖК, коих сотни. Именно в таком ЖК произошла история, описанная в этой статье. В конце написал что есть еще некоторые идеи и вот руки дошли и до одной из них.Все мы знаем ...
Привет, друзья! Представляю вашему вниманию перевод второй части этой замечательной статьи. Ссылка на первую часть. Веб-потоки (web streams) — это стандарт для потоков (streams), который поддер...
До сих пор в этой серии я рассматривал новые минимальные API хостинга, созданные с использованием WebApplication и WebApplicationBuilder. Они обеспечивают более простую модель для создания веб-приложе...
1962В этом году появился первый тонкоплёночный транзистор (thin-film transistor, TFT), разработанный инженером RCA Полом Веймером — изобретателем, получившим множество патентов, связанных с ...
В 1991 году всё больше игр выходило с поддержкой VGA, хотя за EGA ещё держались и не так много игр именно требовали VGA. Для меня же в 1991 начинался период отлучения от РС. Регулярному доступу п...