
Технический долг — вещь, знакомая многим компаниям и программистам. Обычно он копится годами, чтобы потом, подобно сизифову камню, держать в тонусе всех и вся. Под катом — рассказ Альберта Халимова, одного из членов команды «М.Видео – Эльдорадо», о том, как мы справляемся с подобными недугами.
Привет, Хабр!
Расскажу, как мы спасли проект с фронтендом, который изначально разрабатывался внешними подрядчиками, а нам достался уже в тяжёлом состоянии: с устаревшими технологиями, отсутствием единого стиля и внушительным техническим долгом. Тем не менее, нам удалось не только стабилизировать разработку, но и провести полноценную модернизацию — по всем фронтам: от сборки и зависимостей до архитектуры и инфраструктуры.
Вот что мы имели на входе:
Vue 2, Vuex 3, vue-cli, Node.js 16
Папка dist: 22.4 MB
Время сборки: 90 секунд
Два чанка на весь проект: app.js — 550 KiB, vendor.js — 1330 KiB
На выходе получили:
Vue 3, Pinia, Vite, Composition API, TypeScript
Папка dist: 3.5 MB
Время сборки: 20 секунд
Скорость загрузки страниц выросла на 15–25%
И всё это без заморозки разработки новых фич.
Первый звоночек
Первое, что бросилось в глаза — это размер dist и всего два чанка. Команда сборки выглядела так:

Выглядело странно. На деле, вес проекта был почти в два раза меньше — ~11.2 MB. Просто дублировали dist. Понял, что структура сборки вообще не продумывалась — просто как-нибудь, лишь бы билдилось. Удивлён не был. Но понял: впереди много работы.
С чего начал: аудит и приоритизация
Перед тем как лечить, я провёл первичный аудит кода:
Повторяющийся код — форматирование, даты, маски и прочее.
Зависимости-дубли — в одном проекте были и v-mask, и imask, и vue-imask, и vue-input-mask. Аналогично с v-tooltip, vuetify, tooltip.js.
Костыли и антипаттерны — логика, которую не могли объяснить даже авторы.
Список ТехДолга — отдельный документ, жёсткая декомпозиция по категориям: сборка, архитектура, дизайн-система, хранилище, UI-библиотеки и т.д.
Мы не делали рефакторинг в ветках с фичами. Только отдельные MR. Это защищало нас от сбоев, позволило нормально тестировать и не тормозить разработку новых функций.
Оптимизация зависимостей
Первым делом я избавился от «братских» библиотек. Выбрал один пакет на каждую задачу — тот, который поддерживает Vue 3 и активно развивается. В идеале — на TypeScript.
Дальше:
Все утилитарные функции были вынесены в utils
Начал вводить линтер и автоформаттер поэтапно: сначала ESLint с мягкими правилами, затем Prettier, затем husky с pre-commit хуками
Наращивал строгость линтера, переводил предупреждения в ошибки
Через месяц почти весь фронт стал единообразным. И только после этого мы начали миграцию на Vite.
Переезд на Vite
Миграция прошла безболезненно — если не считать один нюанс. При переходе с process.env на import.meta.env я не заметил кусок:

В итоге потеряли данные аналитики за две недели. Да, бывает. Обжёгся — теперь в такие моменты захожу с grep и ищу по проекту вручную все process.env.
Зато после переезда:
Время сборки сократилось до 30 секунд
После замены sass на sass-embedded, минификации всех SVG и кастомизации Vite-конфига — до 20 секунд
Вес dist стал 5.7 MB, а после перехода на Vue 3 и чистки ненужного — 3.5 MB
Плавный переход на Vue 3, Pinia и TypeScript
Здесь стратегия была максимально аккуратной:
Все новые модули писались на Composition API и TypeScript
Pinia существовал параллельно с Vuex
Миграция шла по частям: сначала простые модули, потом отдельные компоненты, только в конце — запутанные сущности с side effects
Так мы не тормозили разработку и не тратили месяцы на «глобальный рефакторинг, который никто не увидит».
Ещё пара мелочей, которые сэкономили часы
Прописал конкретную версию yarn в package.json — CI начал стартовать быстрее на 1.5–2 минуты
Автоматизировал прогон линтера и форматтера — минус тонны мусора в MR'ах
Выводы
Самый важный инсайт — не надо бояться технического долга. Надо просто системно с ним работать. В этом кейсе удалось:
Провести аудит и зафиксировать конкретные участки проблем
Встроить решение в текущие процессы, не нарушая поставку новых фич
Поэтапно провести миграции, не ломая ничего и не вводя хаос
Итоги в цифрах:
Показатель |
Было |
Стало |
Вес dist |
22.4 MB |
3.5 MB |
Время сборки |
90 сек |
20 сек |
Скорость загрузки |
— |
+15–25% |
Спасибо за внимание. Пишите в комментариях о своем опыте работы с техдолгом.
P.S. Хорошие материалы по заявленной теме можно найти также здесь, здесь и здесь.