1 апреля 2025

Кейсы

Разработка

DevOps и инфраструктура

Что делать, когда технологии устаревают. Переход с Knockout.js на React

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

Можно ли сохранить продукт в актуальном состоянии?

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

Какой путь выбрать? Рефакторить код? Выжимать из текущей системы все и переходить на новый продукт? Строить «костыли» для того, чтобы продлить жизнь и как-то адаптировать под современность?

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

Но что делать, если сама технология перестала развиваться и уже невозможно перейти на новые версии, продукт продолжает работать 24/7, а бизнес хочет больше новых фич?

Переход на новую библиотеку

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

Для разработки фронтенда мы использовали библиотеку Knockout.js. На момент старта продукта Knockout.js был отличным решением для создания интерактивных пользовательских интерфейсов и соответствовал нашим требованиям.

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

Выбор в пользу React был сделан не просто так, мы опирались на следующие её преимущества:

Повышение производительности: обеспечение более высокой производительности и скорости работы интерфейса для улучшения пользовательского опыта.

Информационная безопасность: React поддерживает различные библиотеки для тестирования, такие как Enzyme и React Testing Library, которые помогают выявлять и исправлять ошибки. А также использование Virtual DOM, который обновляет только те части реального DOM, которые изменились, что позволяет избежать рисков и уязвимостей при ручном обновлении, как было с Knockout. 

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

Привлечение новых разработчиков: React является одной из самых популярных библиотек для Frontend-разработки, что способствует привлечению профессионалов в команду и улучшению качества кода.

Уменьшение рисков: минимизация Legacy Code снижает риск ошибок, увеличивает стабильность системы и упрощает процесс отладки.

Как перейти на React

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

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

Этапы перехода:

0.         На этапе подготовки реализовали подключение компонентов и сделали синхронизацию состояния приложения с Knockout для минимизации потери данных в случае возникновения проблем.

1.         Внедрение новых стилей. Первым шагом стало улучшение внешнего вида системы. Дизайнеры разработали современные макеты интерфейса, а Frontend - разработчики внедрили новые стили, используя CSS (Cascading Style Sheets).

2.         Параллельное использование React и Knockout. Затем началась постепенная сборка React приложения, которую мы хранили в отдельной папке и постепенно интегрировали в существующий код на Knockout.js, сохраняя при этом работоспособность старого кода. Новые компоненты интерфейса были сделаны согласно разработанным макетам и внутри обновленного Knockout визуально найти их было невозможно.

3.         Интеграция данных. React был собран с использованием сборщика модулей JavaScript Webpack в виде библиотеки, компоненты которой используются в Knockout.js. Файлы изображений и документов (XLSX) копировались в Knockout с помощью copy-webpack-plugin и добавлялись в общую сборку.

Для временной интеграции React-компонентов использовался механизм, при котором React, упакованный в product-ui-kit-lib.js, загружался через fetch и далее встраивался в Knockout. Например, компонент с названием "SomeComponent" становился " product-some-component". Так, мы создали проводку для плавной интеграции React в существующее приложение.

4.           Полная миграция. Для обеспечения согласованной работы React-компонентов и старого кода была создана общая система управления данными, основанная на библиотеке EasyPeasy, надстройка над Redux. Это позволило синхронизировать данные между двумя частями системы и обеспечить корректное отображение информации для пользователей. Наконец, после завершения всех этапов, было принято решение о полном удалении Knockout.js и переходе на React.

Поэтапный подход позволил минимизировать риски и обеспечить плавный переход для пользователей. Продукт при этом продолжал обеспечивать продажи 24/7, активные пользователи постоянно работали с интерфейсом, а функционал постоянно развивался: релизы выходили раз в неделю, продукт пережил значительную переработку пользовательского сценария, адаптировался под потребности бизнеса буквально каждый экран. Тех.стратегия перехода на React не останавливалась ни на неделю.

Вывод

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

При решении таких задач мы придерживаемся следующих принципов:

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

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

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