Материал подготовлен на основе практического опыта команды Compo Soft и посвящён развитию корпоративной платформы Compo B2B Platform — зрелого B2B‑решения, используемого десятками компаний в ежедневных бизнес‑процессах.

Это интервью — разбор реального опыта миграции фронтенда Compo B2B Platform с Angular 13 на актуальные версии фреймворка (в итоге — Angular 19). Команда Compo Soft прошла путь через несколько мажорных апдейтов, замену и переписывание зависимостей, рефакторинг архитектуры и внедрение новых возможностей Angular — от Standalone Components до Vite и non‑destructive hydration.

Ниже — честный рассказ о том, что сработало, где возникли сложности и какие выводы стоит сделать тем, кто только планирует подобное обновление. На вопросы отвечает ведущий фронтенд‑разработчик Compo Soft Дмитрий Федоренко.

Проект: какая область, сколько пользователей, клиентов, фронтенд‑архитектура?

Это B2B‑платформа, ориентированная на задачи средних и крупных предприятий.

Бэкенд написан на Java Spring, фронтенд — на Angular. Монорепозиторий фронтенда содержит два основных приложения:

  • административную панель;

  • клиентский кабинет.

Оба приложения используют общую библиотеку компонентов и утилит.

Исторически в проекте накопилось большое количество зависимостей в package.json, и именно это стало одной из ключевых проблем перед миграцией. На старте у нас был следующий набор UI‑ и вспомогательных библиотек:

  • Nebular;

  • Taiga UI;

  • Angular Material;

  • ngx‑formly;

  • Bootstrap CSS 4;

  • ngx‑easy‑table;

  • tslib.

Какая версия Angular использовалась до обновления?

Мы застряли на версии Angular 13.3, выпущенной весной 2022 года. На тот момент она была стабильной, поэтому мы пропустили несколько мажорных релизов с важными оптимизациями и архитектурными изменениями.

Почему вы решили обновиться именно сейчас — это был бизнес‑ или технический драйвер?

Причины лежали на стыке бизнеса и разработки.

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

Параллельно мы исправляли устаревшие UI/UX‑решения и паттерны, которые регулярно вызывали жалобы клиентов.

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

Однако главной болью стала скорость разработки. Даже небольшие правки в вёрстке или логике требовали ждать 3–6 секунд, пока Ivy‑компилятор пересобирал проект. Холодный старт dev‑сервера и постоянные задержки при работе с UI делали разработку утомительной.

Именно это стало главным мотиватором перехода на актуальные версии Angular с поддержкой Vite.

Какие шаги вы предприняли перед началом миграции? Был ли аудит кода?

Мы начали с простого: создали отдельную ветку и попробовали выполнить ng update. Глубокого аудита на старте не было — и это оказалось ошибкой.

У команды не было достаточной экспертизы в подобных масштабных обновлениях, и мы не до конца понимали риски. Ключевые вопросы, на которые не было ответов:

  • выживут ли основные библиотеки (Nebular, Taiga UI);

  • удастся ли вообще собрать проект;

  • не проще ли начать всё с нуля.

Первая попытка обновления закончилась неудачей: проект начал «ломаться» в самых разных местах. В процессе стало очевидно несколько важных вещей.

  1. Нужен ESLint вместо устаревшего TSLint

    Мы настроили ESLint с максимальным набором правил для Angular и шаблонов. Часть правил перевели в режим warn, второстепенные — отключили. В проекте исторически было много any, и переписывать всё сразу мы не планировали, поэтому тонкая настройка линтера оказалась критичной. Среда разработки (у нас IntelliJ IDEA) должна корректно отображать ошибки линтинга в реальном времени.

  2. AOT‑компиляцию необходимо включать уже в dev‑режиме

    Если этого не сделать, проект может успешно собираться, но фатальные ошибки будут возникать уже в браузере во время работы приложения.

  3. Нужно отказаться от ‑legacy‑peer‑deps

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

Какой подход использовался: big bang, поэтапная миграция, feature toggle?

Подход напрямую зависит от количества и качества внешних зависимостей.

Если библиотек немного, можно обновляться сразу до последней версии. В нашем случае это было невозможно: мы последовательно прошли через Angular 15, 17 и в итоге дошли до версии 19.

Не все сторонние библиотеки поддерживали новые версии фреймворка. Часть из них пришлось заменить на более современные open‑source‑аналоги, что‑то написать с нуля, а от некоторых устаревших решений — отказаться полностью.

Много времени заняло обновление Taiga UI с версии 2 до версии 4. API библиотеки значительно изменился: методы, помеченные как deprecated в третьей версии, были полностью удалены в четвёртой.

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

Мы выбрали гибридный подход, который условно можно назвать «поэтапным Big Bang»:

  • в основной ветке подготовили кодовую базу (обновили второстепенные зависимости, начали использовать Standalone Components в новых модулях, минимально отрефакторили проблемные места);

  • создали отдельную long‑lived ветку, где последовательно выполнили ng update через несколько мажорных версий;

  • изменения вливали в основную ветку не целиком, а логическими блоками — с использованием feature‑флагов.

Какие зависимости оказались блокирующими для перехода?

Наибольшие сложности возникли с Taiga UI и ngx‑formly.

В случае с Taiga UI причиной стала большая разница между версиями 2 и 4. С ngx‑formly пришлось переписать около двух десятков кастомных типов полей, чтобы привести их в соответствие с новой версией библиотеки.

В остальном Angular демонстрирует хорошую обратную совместимость, а автоматические миграции, встроенные в Angular CLI и сторонние schematics, значительно упрощают обновление. Например, ng update @taiga‑ui/cdk закрывает часть проблем автоматически.

Были ли моменты, когда приходилось временно откатываться? Как организовали fallback?

Полноценных откатов не было — изменений оказалось слишком много, и частичные rollback«и не имели смысла.»

Всего получилось три крупных merge‑запроса с более чем тысячей изменений каждый, затрагивающих весь проект. Сначала мы обновили внутренние тестовые среды (PIM и CRM). Это позволило организовать длительный этап внутреннего тестирования: сотрудники активно работали с новой версией интерфейса и оперативно сообщали о проблемах, не затрагивая клиентов.

Как изменилась сборка и CI/CD‑пайплайн?

Существенных изменений не потребовалось. Единственное — в CI пришлось обновить Node.js до версии 22 LTS, чтобы корректно работали настройки module=ES2022 и moduleResolution=bundler в TypeScript.

Какие breaking changes оказались наиболее критичными?

Сам Angular показал себя очень стабильным: даже при обновлении через несколько мажорных версий изменения в коде минимальны.

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

Какие инструменты и ресурсы оказались наиболее полезны?

  • Официальный Angular Update Guide — основной ориентир при миграции.

  • ESLint с правилами @angular‑eslint — помог автоматически исправить множество проблем.

  • Репозитории и документация библиотек на GitHub — часто приходилось заглядывать в исходный код Nebular и Taiga UI.

  • DeepSeek — использовался как «лектор» для быстрого поиска ответов на точечные вопросы.

  • GitHub Copilot в агент‑режиме пробовали применять для миграций и рефакторинга SCSS, но на практике он часто генерировал код, ломающий вёрстку. В итоге ручная работа оказалась быстрее и надёжнее.

Как изменилась производительность, размер бандла и скорость разработки?

Результаты оказались заметными:

  • холодный старт ng serve сократился примерно с 25 секунд до менее чем 6;

  • HMR с Vite теперь отрабатывает менее чем за секунду вместо 3–6;

  • время production‑сборки (ng build ‑configuration=production) уменьшилось примерно на 35%;

  • размер основного бандла сократился незначительно (около 5%), так как основные «тяжеловесы» — сторонние библиотеки, но tree‑shaking собственного кода стал эффективнее.

Что сработало особенно хорошо и что бы вы посоветовали другим командам?

  • Инвестировать время в подготовку: привести в порядок зависимости и отказаться от legacy‑peer‑deps.

  • Заранее продумать стратегию тестирования — внутренний beta‑тест оказался самым эффективным вариантом.

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

  • Максимально использовать автоматические миграции и линтеры.

  • Не спешить с внедрением новых возможностей Anrular вроде signals — сначала убедиться, что команда к этому готова.

  • Внимательно читать release notes и changelogs. В них часто содержится критически важная информация.

Какие риски вы недооценили и что бы сделали иначе?

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

Были ли проблемы с SSR, hydration и компонентной архитектурой?

С SSR (Angular Universal) сложности действительно были. Новая non‑destructive hydration потребовала адаптации: мы сталкивались с ошибками NG0500 из‑за несовпадения DOM на сервере и клиенте.

Основные причины:

  • прямые манипуляции с DOM через document или ElementRef в ngOnInit;

  • использование setTimeout без корректной обработки на сервере;

  • сторонние библиотеки без поддержки SSR.

Проблемы решались аудитом кода и оборачиванием таких операций в isPlatformBrowser. Переход на Standalone Components, напротив, прошёл очень гладко и стал одним из самых позитивных изменений за всё время миграции.

Каковы перспективы работы на Angular 19 и дальнейшие шаги?

Vite‑сборка, Signals, новый control flow, Standalone API и обновлённый синтаксис шаблонов делают код более декларативным и понятным. Мы планируем аккуратно наращивать опыт работы с signals, полностью отказаться от NgModules и глубже поработать с SSR и гидратацией. После этой миграции мажорные релизы Angular перестали пугать.

Практический чек-лист: обновление проекта до Angular 19

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

Шаг 1. Ознакомьтесь с примечаниями к выпуску Angular 19 

Изучите release notes и журнал изменений, чтобы понять, какие новые возможности появились, какие API объявлены устаревшими и какие изменения могут нарушить обратную совместимость.

Шаг 2. Создайте резервную копию проекта

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

Шаг 3. Обновите глобальную версию Angular CLI

Выполните команду:
npm install ‑g @angular/cli@19

Шаг 4. Обновите Angular в проекте

Запустите обновление основных пакетов:
ng update @angular/cli@19 @angular/core@19

Шаг 5. Обновите версию TypeScript

Установите рекомендованную версию:
npm install typescript@5.6 ‑save‑dev

Шаг 6. Обновите остальные зависимости Angular

Проверьте и обновите связанные пакеты:
ng update @angular/forms @angular/router @angular/material

Шаг 7. Актуализируйте сторонние зависимости

Выполните npm outdated и обновите устаревшие пакеты с помощью npm install package‑name@latest, уделяя особое внимание совместимости с Angular 19.

Шаг 8. Разберите breaking changes и устаревшие API

Последовательно устраните критические изменения, связанные со Standalone Components, новым control flow и системой гидратации.

Шаг 9. Запустите и протестируйте приложение

Проверьте проект с помощью ng serve, ng test и ng e2e, уделяя внимание SSR и клиентской гидратации, если они используются.

Шаг 10. Оптимизируйте конфигурации сборки

Обновите angular.json и tsconfig.json в соответствии с рекомендациями Angular 19.

Шаг 11. Выполните production‑сборку

Запустите:
ng build ‑configuration=production

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

Шаг 12. Развертывание и мониторинг

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

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


  1. tizian
    18.12.2025 09:14

    Очень странный кейс - сидеть 3 года и ничего не делать, а потом все переписывать.

    За монорепом нужно следить и ухаживать, поддерживать все в актуальном состоянии. Постоянное обновление Angular и NX, а также pnpm audit


    1. IgorN Автор
      18.12.2025 09:14

      Кто сказал что никто ничего не делал) Не обновляли по стратегическим причинам: сначала приоритет был на стабильности production (риск breaking changes в Angular 14-17 с Ivy, SSR и standalone components мог сломать legacy-функционал) и команда фокусировалась на бизнес-фичах без техдолга (работает - не трогай). Ну и если глянуть на Netflix или GitHub, то они тоже порой не бегут за апдейтами по 2-3 года. Так что местами это нормальная практика.


      1. tizian
        18.12.2025 09:14

        Нет, это не нормальная практика. И со стабильностью и с безопасностью - она никак не связана. Как я указал выше, нужно во время обновляться и подтягивать все проекты. Если это делать системно - все работает отлично и никаких side effects не возникает, прод работает ожидаемо, хоть с SSR, хоть без.

        Как на моей прошлой работе, где монореп был гигантский, с кучей проектов и тысячами разработчиков, так и на текущей работе - где монореп, уже по-меньше - без разницы, версия ангуляра всегда поддерживается в актуальном состоянии. Обычно, спустя 1-2 месяца после релиза, все обновляем. А в промежутках еще и минорные версии подтягиваем...


        1. bazzzman
          18.12.2025 09:14

          Обновление спустя 1-2 месяца после релиза - это круто. Вы молодцы, завидую.

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

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

          3. "никаких side effects не возникает" - здесь вот не соглашусь. Это риск. Ни раз нарывались на регрессии как в Ng так и в свежих версиях библиотек. Для себя выбрали стратегию не частых обновлений, с вдумчивым и растянутым по времени бета-тестом. Когда сотрудники могут 1-2 месяца работать с next версией продукта и только после этого будет общий релиз.


          1. tizian
            18.12.2025 09:14

            Так, у всех большая кодовая база. И обновление самого Ангуляра - это не самая сложная задача. Гораздо сложнее - это статический анализ кода и написание патчей под сторонние зависимости.


            1. bazzzman
              18.12.2025 09:14

              Не понимаю, что вы доказываете? Критика ради критики.

              Вот смотрите, у нас Angular и Taiga UI, супер-крутая библиотека от Тинькова. Angular 16 выходит в мае 2023, а Taiga с поддержкой Angular через 15 месяцев, в августе 2024. Как в этом случае обновиться за 1-2 месяца после релиза?

              Менять тайгу на что-то другое, переписывать код приложения и переучиваться всем на ходу? Ставить в legacy peer deps режиме и ловить баги? Если зависимостей мало или они быстро обновляются - можно порадоваться за вас. Если нет - обновляемся через 1-1.5 года после выпуска свежего ангуляра.


              1. tizian
                18.12.2025 09:14

                Не понимаю, что вы доказываете?

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

                Но теперь понятно, раз вы юзаете Bootstrap и внешние UI-либы - соответственно, делаю вывод что у вас мало компетенций по данной теме. Зачем тянуть к себе в проект такие простые штуки... Видимо, вы еще не выросли.

                Ну, ок.


                1. bazzzman
                  18.12.2025 09:14

                  Да, мы не спешим очень быстро меняться и следовать за модой которая во фронте часто меняется. В этом плане да, не выросли. Неспешно используем Angular ещё с первой, js версии и постепенно дошли до 19-ой. Bootstrap 5-ой версии тоже закрывает часть наших задач. Он хорошо документирован, прост и продуман, в него легко погружать программистов. Менять его тоже пока не собираемся. Не спешим никуда, медленно и поступательно развиваемся.


                  1. tizian
                    18.12.2025 09:14

                    Теперь все встало на свои места :)

                    Сразу чувствуется влияние бэкендов. Это у них один раз настроил и все, ближайшие годы, пока не прилетит - ничего не трогаем :)

                    На фронте - другой подход. Для примера запустите в своем монорепе аудит (npm/pnpm audit или какой у вас пакетный менеджер используется), в идеале должно быть 0 критических уязвимостей.


  1. dananaprey
    18.12.2025 09:14

    Спасибо за интересную статью! Подскажите, насколько я понял вы ещё не перешли на Vite? Мы попробовали, но новый сборщик стал дробить весь код на очень маленькие чанки, а приложение не малое и по итогу скорость загрузки уменьшилась (особенно на низкой скорости), так как у браузера не бесконечное количество потоков. Вы с таким пока не столкнулись?


    1. bazzzman
      18.12.2025 09:14

      Здравствуйте. Мы на Vite и маленькие чанки это прекрасно.

      Плюсы stand alone и небольших чанков

      • Возможность использовать lazy load компонентов прям в роутинге https://angular.dev/reference/migrations/route-lazy-loading

      • Tree shaking сильно эффективнее работает с мелкими чанками

      • Один большой модуль даст вам более быструю полную загрузку приложения, но доступным для действия пользователя приложение станет заметно позже. Т.е. в браузере долгое время будет отображаться процесс загрузки, вместо (пусть даже частично) доступного интерфейса. Stand alone даёт более быстрый интерактив в браузере

      • Так же маленькие чанки дают возможность локально использовать Hot Module Replacement (HMR) для стилей и шаблонов. Это значительно ускоряет обновление в браузере при активной работе со стилями или html

      Что делать если есть проблемы с исчерпанием лимита соединений

      • Смотрите детально почему вы загружаете много всего при старте. Это в самом деле необходимо?

      • Можно использовать супер-крутую штуку @defer - https://angular.dev/guide/templates/defer для lazy load части компонентов. Вы можете совсем не грузить код с которым пользователь не работает и делается это элементарно, без сложное конфигурации. У @defer есть разные стратегии загрузки кода - idle, viewport, interaction, hover, ... Возможно сможете перенести часть функционала на отложенную загрузку и облегчите приложение в целом.

      В итоге мое мнение - чем меньше будут чанки тем лучше. Даже если их будет много.


      1. dananaprey
        18.12.2025 09:14

        Спасибо за подробный ответ) Насколько у вас большое приложение и используете ли вы preloading чанков?

        Мы как раз сейчас движемся в сторону оптимизации загрузки, пока вернулись на webpack. Оптимизировали размеры основных чанков, standalone с lazy routing уже настроен, добавили defer, настроили Service Worker и перестали грузить то, в чём не было необходимости. В ближайшее время, думаю, снова попробуем Vite, должно стать получше, но уверен нужны будут ещё оптимизации, спасибо за совет!


  1. bazzzman
    18.12.2025 09:14

    У нас два приложения на 4+ и 5+ мегабайт в прод сборке. Чанки анализируем через http://esbuild.github.io/analyze/ после сборки ng build --stats-json
    Хороший анализатор. Рекомендую.

    Прелоад не используем. Наоборот, грузим только то, что нужно сейчас пользователю. Приложение у нас с настроенным service worker'ом, он фоном смотрит на сервер и если был свежий релиз - сам тихонько загрузит все чанки и предложит обновиться в UI. Это удобно. Пользователь не отвлекается на загрузку и видит кнопку обновления только если все чанки были уже загружены браузером.

    Да, холодный старт будет медленнее, но не могу придумать сценариев в нашем окружении где webpack был бы быстрее и оптимальнее Vite. Гибче, может быть, но не быстрее. Не зря на него официально перевели Angular. Надо смотреть ваше приложение, гонять его в Performance анализаторе консоли Google Chrome с разными настройками и искать узкое место. Сервер http2? Он корректно настроен? Надо смотреть зачем вам сразу при старте грузить много кода если можно показать UI, дать с ним работать и догружать куски интерфейса на ходу. Общих рекомендаций к сожалению не дам, надо в детали погружаться.