Основной веб-сайт Vercel, некогда являвшийся единым крупным сайтом Next.js приложение, обслуживающее как посетителей нашего веб-сайта, так и панель управления для входа в систему. Но по мере того, как компания Vercel росла, в этой системе появились возможности для совершенствования. Время сборки росло, управление зависимостями становилось все более сложным, а рабочие процессы требовали оптимизации. Незначительные изменения привели к полномасштабным сборкам, повлияв на изолированную разработку и конвейеры CI.

Было ясно, что необходимы изменения.

Переосмыслив нашу архитектуру, мы перешли на вертикальные микрофронтенды, что упростило процесс разработки и более чем на 40% сократило время предварительной сборки и локальной компиляции для разработки. Оптимизированные зависимости за счет удаления кода для других микрофронтендов также уменьшили вес страницы и повысили производительность для конечных пользователей, улучшив основные веб-функции, такие как время отрисовки с наибольшим содержанием контента (LCP) и взаимодействие с Next Paint (INP).

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

К слову, о догфудинге...

Давайте посмотрим, как нам это удалось.

Использование Turbo

Turbo - это высокопроизводительная система сборки для JavaScript и TypeScript приложений. Она разработана для масштабирования монорепозиториев, а также ускоряет рабочие процессы в однопакетных рабочих пространствах.

https://turbo.build/

Нашим первым шагом было сосредоточиться на улучшении локальной компиляции, времени сборки и рабочих процессов CI. Monorepo работает на базе Turborepo, что позволило нам оптимизировать задачи с помощью таких функций, как удаленный кэш и --affected. Внедрение Turbopack значительно ускорило локальную разработку.

Но, внося эти улучшения, мы поняли, что модель с одним приложением также больше не нужна для Vercel.com. Логическое разделение приложения позволило нам избежать ненужной работы при каждой сборке и компиляции, что еще больше увеличило скорость разработки.

Взвешивание горизонтального или вертикального разделения

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

  • Вертикальные микрофронтенды: разделение по пути, когда каждая страница обрабатывается одним приложением

  • Горизонтальные микрофронтенды: разделение по функциям, когда несколько приложений запускаются на одной странице

Горизонтальное и вертикальное разделение приложения
Горизонтальное и вертикальное разделение приложения

Здесь нет правильного или неправильного ответа, и у каждого есть свои компромиссы. Каждый подход может принести существенные преимущества в зависимости от варианта использования. Книга Луки Меццалиры о микрофронтендах - хороший источник по этой теме.

Вертикальные разбиения обеспечивают согласованность, но могут затруднять навигацию при переключении между приложениями, поддерживаемыми различными микрофронтендами. Такие методы, как предварительная выборка и API, такие как правила спекуляции Chromium, могут помочь, но имеют ограничения, такие как повышенное использование ресурсов и ограниченная поддержка браузером.

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

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

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

Наш путь миграции

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

  • Маркетинг

  • Документация

  • Панель управления для входа в систему

Поскольку мы используем Next.js, мы использовали функцию Multi-Zones Next.js, которая поддерживает вертикальные микрофронтенды.

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

Продолжая использовать monorepo и централизуя код в пакетах в рамках monorepo, мы обеспечили согласованность общих компонентов, но при этом сохранили простоту, постепенно выделяя ключевые области. Такие инструменты, как Turborepo и Dependency Cruiser, помогли упростить этот процесс.

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

Используя Feature Flags, мы смогли постепенно перенаправлять трафик с монолитного интерфейсного приложения still-live на новые микрофронтенды. Это позволило нам минимизировать риски и проверить улучшения производительности перед удалением старого кода. Когда новая страница безошибочно обслуживала трафик в течение как минимум недели, мы удалили код из существующего приложения, постепенно сокращая зависимости и время сборки.

Во время постепенной миграции страница существует как в исходном интерфейсе монолита, так и в новом интерфейсе microfrontend. Feature Flags управляют маршрутизацией до тех пор, пока версия интерфейса microfrontend не заработает в полную силу.
Во время постепенной миграции страница существует как в исходном интерфейсе монолита, так и в новом интерфейсе microfrontend. Feature Flags управляют маршрутизацией до тех пор, пока версия интерфейса microfrontend не заработает в полную силу.

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

Уроки и поиск компромиссов

После успешного внедрения микрофронтендов для Vercel.com мы применили тот же подход к другим сайтам, таким как страница 2024 Next.js Conf, которая работает как отдельное приложение от nextjs.org. С помощью этой инфраструктуры мы могли бы выделять отдельные области в независимые приложения, ускоряя циклы разработки, поскольку команды Next.js Conf и Next.js разработчиков могли выполнять итерации быстро и независимо друг от друга.

Тем не менее, были проблемы. Мы столкнулись с некоторыми проблемами и работали над тем, чтобы производительность не снижалась, в частности, используя такие инструменты, как Speed Insights для мониторинга реального использования и панель инструментов Vercel для оповещения о смене макета и времени взаимодействия.

Мы сразу поняли, что тестирование микрофронтендов локально и в режиме предварительного просмотра является сложной задачей. Такие функции, как черновой режим, работали некорректно, а узкие места в производительности, такие как сложная навигация, были известными проблемами. Чтобы решить эти проблемы, мы применили такие стратегии, как предварительная выборка и рендеринг с использованием правил спекуляции Chromium.

Пример преодоления компромиссов:

Чтобы уменьшить влияние сложной навигации, мы начинаем с загрузки ресурсов начальной страницы (JavaScript и CSS) для загрузки в кэш браузера, как только ссылка становится видимой. Это означает, что при переходе пользователя эти ресурсы загружаются из кэша. Однако страница по-прежнему требует рендеринга и извлечения оставшихся ресурсов, таких как HTML.

Мы делаем еще один шаг вперед, предварительно отображая страницы при взаимодействии с пользователем (например, при нажатии на ссылку). При этом страница отображается в фоновом режиме, включая все сетевые запросы и обработку, поэтому при появлении пользователя все происходит мгновенно. Такой подход обеспечивает баланс между производительностью и использованием ресурсов — только предварительная выборка и предварительный рендеринг в нужное время, что позволяет избежать перегрузки устройства и при этом обеспечить желаемый результат.

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

Заглядывая в будущее

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

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

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

Комментарии (1)


  1. cmyser
    25.10.2024 11:07

    Было бы интересно почитать как у вас происходит сборка и деплой в монорепе