Привет, меня зовут Ваня, недавно я выступил на CodeFest 11, где рассказал про путь Тинькофф Бизнеса на фронтенде от одного приложения к сотне. Но так как в ИT очень быстро все меняется, а ждать запись еще долго, сейчас я тезисно расскажу о нашем шестилетнем путешествии в дивный мир микрофронтенда!
![](https://habrastorage.org/getpro/habr/upload_files/7eb/6c9/8e4/7eb6c98e4f0f3686a34aeae7d40b5ccd.png)
Мою статью можно разбить на две части. В первой части вас ждет история развития через призму бизнеса. А во второй — рассказ о том, как мы адаптировались к новым вызовам.
Этапы развития
Одно приложение на AngularJS в 2014—2015 годах.
Миграция на Angular2.
Утяжеление десяти приложений новой функциональностью.
Переход к микросервисам и разбиение на 100 приложений.
На дворе начало 2015 года. К нам приходит бизнес и говорит: «Мы хотим сделать зарплатный проект! Посмотрите, что есть сейчас на рынке по технологиям, и сделайте». Выбираем AngularJS, быстро создаем приложение. Спустя некоторое время аппетиты вырастают, мы создаем еще два сервиса. На этот момент фронтенд-приложения никак не взаимодействуют друг с другом.
Компания растет, мы доходим до десяти приложений в 2017 году. Команды еще не так сильно разрослись, но уже чувствуется локализация некоторой экспертизы. Для шаринга информации выделяется особая роль — «архитектор». С одной стороны, это самый технически прокачанный человек, с другой — евангелист наших подходов, который на одном языке общается как с бизнесом, так и с новичком в компании.
![](https://habrastorage.org/getpro/habr/upload_files/dab/6cd/394/dab6cd39414dc64e069d2a5792a84b95.png)
В 2017—2018 годах мы подумали, что уже хватит отдельных репозиториев, и стали добавлять фичи в существующие проекты и репозитории вместо создания новых.
В одном из проектов у нас было пять фронтенд-команд, в каждой по 3—5 человек, то есть в самый лучший момент в одном проекте работали 25 фронтендеров! Иногда было действительно больно: ты вот-вот замержишь свою задачку, но нет! Перед тобой кто-то успевает и все твои пайплайны начинают проходить заново! До сих пор мне не по себе от этих воспоминаний.
В какой-то момент мы осознали, что сборка приложения занимает уже полчаса и будет только расти, и решили распиливать наши монолиты на микросервисы.
![](https://habrastorage.org/getpro/habr/upload_files/9a6/02c/bf6/9a602cbf6428009fb87f1591e4609779.png)
Вот так быстро и пролетели шесть лет эволюции наших подходов. Теперь взглянем на наш путь через призму своих решений для микрофронтенда.
Сайдбар
Первые три приложения мы подружили между собой с помощью сайдбара.
В каждое приложение он встраивался с помощью ссылки на скрипт, который загружал на клиент полноценное приложение. Сайдбар отвечал за авторизацию, продукты клиента и текущий роутинг страницы, мог отправлять уведомления и загружал мессенджер на страницу. Как мы видим, довольно много возможностей у одного сервиса.
По технической части это iframe со всеми плюсами и минусами, о которых довольно подробно расписано в докладе Яндекса. Но больше всего нам не нравилась перезагрузка страницы на каждую смену продукта. Это мешало переиспользованию состояния клиента, требовало каждый раз обращаться к бекенду и добавляло некрасивые «мерцания» страницы при переходах.
![Подсвеченная область – отдельное приложение Сайдбар Подсвеченная область – отдельное приложение Сайдбар](https://habrastorage.org/getpro/habr/upload_files/4ca/00f/fbe/4ca00ffbe7b61c3241e997729fb49617.png)
Frame Manager
Именно рваные переходы мы убрали с появлением Frame Manager'а (далее буду называть его ФМ).
![Подсвеченная область – отдельное приложение Frame Manager Подсвеченная область – отдельное приложение Frame Manager](https://habrastorage.org/getpro/habr/upload_files/dac/7b4/1b3/dac7b41b35b763309428b0b3dae57324.png)
В отличие от сайдбара, который встраивался в приложение с помощью iframe, ФМ находился на странице всегда и сам встраивал в себя приложения.
![Слева – концепция сайдбара (было), справа – Frame Manager'а (стало) Слева – концепция сайдбара (было), справа – Frame Manager'а (стало)](https://habrastorage.org/getpro/habr/upload_files/f93/a39/3dc/f93a393dcaafc281a2dfe5a3026c2ed7.png)
Для клиента ФМ так же не заметен, как и сайдбар, но для нас он выполняет уже больше функций. Кроме рейтинга, списка продуктов и авторизации он может передавать состояние между приложениями, например через глобальный window. Пользователь больше не замечает, что ходит между несколькими отдельными приложениями, так как верхняя часть у него никуда не пропадает и визуально весь процесс выглядит как подгрузка контента на одну страницу.
В плане интеграции приложения тоже все поменялось:
Раньше приложению-клиенту достаточно было подключить необходимый скрипт к себе в index.html.
Теперь все приложения ФМа хранятся в отдельной конфигурации и используются как единый источник правды.
Минус этого подхода — мы все равно остались с iframe, который нам не особо нравился из-за особенностей работы с ним.
Однажды через поддержку к нам обратились пользователи с ситуацией: «Раньше у меня работал плагин для Google Chrome, а с недавнего времени именно на вашем сайте перестал. Почините, пожалуйста!» Обычно на такие просьбы не реагируют: пользователь что-то себе установил — пусть сам и разбирается. Но только не в нашей компании. Команда долго изучала вопрос, смотрела, какое окружение у клиента, версия браузера и все-все, но ответа так и не было. В итоге мы полностью повторили окружение, загрузили себе плагины и путем дебагинга установили, что данный плагин не работает, если у iframe динамически менять атрибут src или пересоздавать фрейм. К сожалению, мы так и не смогли исправить такое поведение, поскольку на этой концепции построено все взаимодействие ФМ и дочерних приложений.
Бесфрейм-менеджер
Однажды мы собрались и подумали: «Несколько лет страдаем от iframe. Как перестать страдать? Давайте просто уберем его!» Сказано — сделано. Так и появился бесфрейм-менеджер — с фантазией у нас, конечно, не фонтан ;-)
Ключевые отличия от предыдущей версии — самописная изоляция и работа с микрофронтендом вместо фрейма. На мой взгляд, лучше всего мотивацию создания отражает слайд из моей презентации:
![](https://habrastorage.org/getpro/habr/upload_files/4b9/619/56a/4b961956a457dcd508672d695f7a10d8.png)
В решении — три составляющие:
Webpack-плагин — основа нашего решения, подробнее о которой можно прочитать в статье Игоря.
Angular builder — обвязка для настройки и запуска плагина.
Angular schematics — скрипт для упрощения работы с файловой структурой с помощью AST.
В 2021 году плагин становится менее актуальным, потому что вышел Webpack 5 с Module Federation, но напомню, что мы вели разработку в 2018 году, а Angular стал поддерживать последнюю версию вебпака лишь с двенадцатой версии, которая вышла 12 мая 2021 года. Мы пока не уверены, сможет ли MF заменить наше решение, и изучаем комбинацию подходов.
Что же касается других решений, на которые можно было перейти для отказа от iframe, то это Single SPA. Он всем хорош и очень популярен, но в плане Angular есть небольшой дисклеймер.
![https://single-spa.js.org/docs/ecosystem-angular/ https://single-spa.js.org/docs/ecosystem-angular/](https://habrastorage.org/getpro/habr/upload_files/fce/b05/897/fceb05897fdbf909ac07d5f0ebce284a.png)
Мы понимали, что глобально менять концепцию фреймворка нам никто не даст, потому решили доделать имеющийся.
Что же касается Angular builder и schematics, то они нужны, чтобы разработчики, которые будут интегрировать наше решение к себе, не выполняли километровую инструкцию, а просто написали в консоли:
ng update @scripts/deframing
И вся магия подключения произойдет у них на глазах, но не потребует никакого ручного вмешательства. Подробнее с работой билдеров и схематиков можно ознакомиться в классной статье.
Тестирование
Для нас важным моментом является автоматическое тестирование, тем более в проекте, от которого зависят все остальные команды. Путем проб и ошибок мы пришли к такому разделению тестового покрытия:
Можно прогонять тесты совместно с локальным ФМом. Так разработчики всегда могут быть уверены, что на текущей продовой сборке все работает и выглядит так, как и задумывалось.
Сам ФМ определяет несколько жизненно важных процессов, работоспособность которых гарантирует при любых условиях: это авторизация, роутинг, работа с данными приложений. Для этого создаются приложения-стабы (stub), суть которых — подключиться к ФМу и выполнить одну из вышеперечисленных функций. То есть на каждое изменение кодовой базы ФМа будет гарантированно работать эта функция.
Ну и как же обойтись без описания багов, которые мы встретили на своем пути. Их тоже можно поделить глобально на две группы: накопление стилей и сторонние библиотеки.
Накопление стилей — пользователь «гуляет» между приложениями, и у него накапливается состояние. Допустим, один из разработчиков написал:
.my-pretty-header {
display: none;
}
Если у кого-то из следующих приложений есть такое же название класса, этот стиль применится так же!
Пример: диалог решил спрятаться под меню, чтобы пользователь не догадался, что от него требуется:
![](https://habrastorage.org/getpro/habr/upload_files/811/65f/bd7/81165fbd79f56a80c06e17afa6a69eb6.png)
Этот тип багов мы решили путем префикса по id приложения для всех стилей, чтобы они не имели глобальную видимость.
Сторонние библиотеки — если на одной странице два и более приложения используют библиотеку, которая на старте создает новый инстанс, то получается такая картина:
![](https://habrastorage.org/getpro/habr/upload_files/b62/e59/63b/b62e5963b0c2f8bbe60bf0f4c415d029.png)
То есть библиотека пытается дважды запуститься и второй сервис затирает первый, что ломает поведение обоих. Это мы исправили путем небольших доработок библиотек.
Microzord
Вот мы и прошли шесть лет технического развития нашего решения. И что может быть лучше, чем поделиться этим опытом с сообществом? Все наработки будут публиковаться под npm scope @microzord
с открытым кодом на Гитхабе.
![](https://habrastorage.org/getpro/habr/upload_files/3d5/825/a81/3d5825a81c54471fba57039909a9a033.png)
В планах — предоставить клиент не только для Angular, но и для работы с другими фреймворками. Сейчас лишь небольшая часть вынесена на Гитхаб, но будьте уверены, ребята не заставят себя ждать и в одной из следующих статей расскажут о гитхабе поподробнее.