Современный интерфейс — это больше, чем просто формы и стили.
Это сложные модели, составные компоненты, графика, интерактивные редакторы, системы локализации на несколько языков и многое другое.
Для разработки и поддержки такого левиафана требуется множество разработчиков — писать еще больше кода.
Команда становится больше, кодовая база растёт — работать с монолитом становится всё сложнее.
Казалось бы, выхода нет – сиди и мучайся.
Но мы смогли выйти из этой сложной ситуации.
Меня зовут Влад Коротун, я ведущий front-end разработчик в одной из продуктовых команд. hh.ru .
В этой статье я расскажу вам о нашем пути от большого монолита к так называемым «микрофронтендам».
Основные проблемы
Для начала давайте рассмотрим основные проблемы, с которыми мы столкнулись при работе с монолитом:- Многие команды одновременно пишут в разные части проекта.
Трудно определить, кто несет ответственность за тот или иной код.
- В монолите сложно проводить рефакторинг и внедрять новые технологии.
- Сборка монолита с каждым годом занимает все больше времени.
При отладке очень неприятно ждать полминуты, пока проект соберётся и можно будет увидеть результат своих правок.
- При выпуске наблюдается спешка, часто возникают конфликты.
- Автотесты релиза могут занимать до двух часов, что также вносит неприятные коррективы в ход работы.
- Монолит обычно накапливает много унаследованного кода, который никто не хочет трогать, но его приходится поддерживать.
И мы нашли выход из этой ситуации — вынести части проекта в отдельные микросервисы.
Попытка написать
Не так давно перед нами стояла задача добавить веб-интерфейс чата между соискателями и работодателями.По своей сути она отличается от других страниц в hh.ru , поскольку он заполняет все доступное пространство, имеет боковую и верхнюю панели и выглядит как отдельное веб-приложение.
Вполне логично выделить этот интерфейс в отдельный сервис, чтобы не упираться в установленные ограничения основной кодовой базы.
Поскольку у нас уже был опыт встраивания сторонних ресурсов с помощью iframe, мы решили использовать уже знакомый подход — разместили чат на отдельном домене и интегрировали его в основной сайт с помощью iframe. Это также позволило открыть чат в отдельной вкладке без подключения к основному сайту – удобно для пользователей, которые проводят много времени в переписке.
Связь с основным сайтом осуществлялась через сообщения postMessage. Благодаря тому, что чат получил собственную независимую кодовую базу, он стал нашим первым сервисом на React 17.
Прокси-страницы
Работать с iframe не всегда удобно.В случае с чатом, который является скорее веб-приложением, чем макетом страницы, iframe не вызвал никаких проблем.
Чат открывается в виде наложения и расширяется, заполняя все отведенное ему пространство.
Но когда дело доходит до встраивания страницы, возникают проблемы с управлением высотой iframe. Хоть контент и может менять свою высоту, на высоту самого iframe это никак не повлияет. Конечно, проблему можно решить с помощью JS — проверку высоты контента по таймеру и настройку высоты контейнера, но это очень затратно с точки зрения производительности.
Поиск подходящего решения привел нас к системе встраивания целой страницы в основной сайт, когда все скрипты, стили и сам макет загружаются в основной документ. Встроенные службы используют модули CSS для своих собственных классов, поэтому между привязкой и содержимым встроенной страницы нет совпадений стилей.
Но здесь есть проблема — стили нашей повторно используемой библиотеки компонентов.
Обычно сервисы выпускаются независимо друг от друга, поэтому они могут использовать разные версии нашей библиотеки компонентов.
А поскольку его стили, помимо React, используются еще и в коде Legacy-xsl, их имена не хэшируются.
Из-за несоответствия версии основного сайта и встроенной страницы могут возникать конфликты.
С другой стороны, в случае встраивания целой страницы с основного сайта используются только хедер и футер, которые имеют свою разметку, а значит, конфликты в стилях наших повторно используемых компонентов маловероятны.
Компоненты прокси
Иногда хочется вынести в отдельный сервис не всю страницу, а конкретный компонент. Это может быть виджет на главной странице или другой блок, встроенный в макет существующей страницы.Поэтому следующим витком эволюции наших микрофронтендов стали прокси-компоненты.
Прокси-компоненты, как и прокси-страницы, используют нашу библиотеку компонентов.
Поскольку прокси-компонент встроен в существующие страницы сайта, которые также используют эту библиотеку, увеличивается вероятность конфликтов стилей.
Чтобы избежать конфликтов, мы решили изолировать DOM прокси-компонента с помощью ShadowRoot. Весь код встроенного компонента, включая подготовленный SSR макет, стили и скрипты, мы размещаем в изолированном контейнереshadowRoot. В качестве бонусаshadowRoot наследует стили своего контейнера, например, цвет текста.
Это позволило нам без дополнительных доработок размещать компоненты в блоках, которые можно отображать с черным фоном и белым текстом или наоборот — с белым фоном и черным текстом.
Цвет текста в любом случае будет унаследован от родителя.
А что насчет ССР?
Чтобы ускорить отображение страниц для пользователя и улучшить индексацию сайта, мы используем Server-Side-Rendering. Первая версия интеграции прокси-компонентов загружала код непосредственно в браузер пользователя.Соответственно, первый рендер, пришедший с сервера, вообще не включал в себя прокси-компоненты.
Мы хотели добавить в результат первого рендеринга макет сервисов, чтобы контент индексировался и весь контент страницы сразу был виден в браузере.
И вот что мы сделали: Мы перенесли инициализацию прокси-компонентов из браузера в наш BackendForFrontend на Python. Если нужно было отрендерить прокси-компонент, обработчик ходил в сервис и помещал результат в специальный узел.
При сборке страницы полученный от сервиса результат встраивался в нужное место шаблонизатором.
Далее полученные данные переносились в ShadowRoot и происходил гидрат — процесс оживления макета с реакцией, сравнивающей полученный с сервера макет с результатом первого рендера.
Недостатки
Единственный недостаток работы с ShadowRoot таким способом — первые пару секунд пользователи видят фрагменты страницы без стилей.Почему это происходит? Стили прокси-компонента могут конфликтовать с основным документом, поэтому мы не помещаем их в DOM при первом рендеринге.
Стили появляются только тогда, когда весь код перенесен в ShadowRoot.
Что мы собираемся с этим делать?
Мы планируем перенести нашу библиотеку компонентов в модули CSS. Поскольку его код поставляется «несобранным» и собирается самим сервисом, имена классов получат уникальные префиксы, и в сборку будут включены только те стили, которые в нем используются.
Как только это будет сделано, мы сможем отказаться от ShadowRoot и загрузить стили и макет непосредственно в основной документ. Ведь необходимость изолировать контент полностью отпадет.
Полученные результаты
Мы уже некоторое время живем по этой схеме, поэтому обнаружили некоторые незначительные неудобства использования прокси-сервисов.Например, вам часто приходится решать сразу две задачи: разработать новый компонент и интегрировать его в основной сайт. А если контракт изменится, придется создавать обратно совместимые релизы, поскольку микрофронтенды и основной сайт выходят в разное время.
Управлять зависимостями становится еще сложнее — их приходится обновлять отдельно в каждом сервисе.
А поскольку зависимости обновляются одновременно, то часто возникает расхождение версий от сервиса к сервису.
Это может привести к различиям в стилях повторно используемых компонентов.
Например, мы перекрасили кнопки в библиотеке компонентов, и пока каждый сервис не обновит эту зависимость, на его встроенных страницах и компонентах будут отображаться кнопки, отличные от кнопок на основном сайте.
Также, если в используемых пакетах возникают уязвимости, необходимо поднимать версии во всех проектах, а их число вскоре превысит десять.
Однако у нас есть больше преимуществ:
- Сервис собирается гораздо быстрее монолита — 1-2 секунды против 15. Быстрее видишь результат — быстрее принимаешь решения.
- Никакой спешки при выпуске, когда из-за конфликта задач весь поезд останавливается до выяснения ситуации.
- Автотесты быстрые.
На основном проекте это чуть больше часа, а в сервисе мы запускаем только те тесты, которые затрагивают фрагменты со встроенными прокси-компонентами или страницы.
Задавайте вопросы в комментариях, рассказывайте, как вы режете свой монолит. Счастливого мая! Теги: #Разработка сайтов #микросервисы #react #iframe #shadowdom
-
Влияние Социальных Сетей На Бизнес
19 Oct, 24 -
Первый Бюджетный Фаблет
19 Oct, 24 -
Технические Интервью: Советы
19 Oct, 24 -
Червь Морриса – Он Был Первым
19 Oct, 24