«Бизнесу это невыгодно!», «Мы не будем вкладывать в это ресурсы», «Зачем, оно и так отлично работает» — какие аргументы можно привести против всех этих высказываний?
Миграция на Vue 3 по факту это технический долг, на который обычно выделяют по минимуму времени. Проекты работают, пользователи не жалуются, а небо всё также синее. Можно жить дальше?
Можно! Но есть моменты на которые важно обратить внимание и донести бизнесу.
В этой статье хочется поговорить про две важные стороны миграции: почему переход на Vue 3 важен для бизнеса и разработки, а также как подготовить большой legacy-проект к миграции ещё до первого изменения в коде.
Будет полезно: разработчикам, техлидам, руководителям команд и тем, кто отвечает за развитие продукта.
Почему миграция важна
Начнём с причин, почему откладывать миграцию на Vue 3 — не лучшая идея.
-
Безопасность. Самый, на мой взгляд, важный момент, который бизнес не сможет игнорировать. Версия Vue 2 с конца 2023 года больше не поддерживается, а это значит, что больше никаких патчей и обновлений. Любая уязвимость — проблема разработчиков и команды.
-
Устаревшие инструменты. Со временем начинаешь ощущать, что технологии ушли далеко вперёд, а проект стоит на месте. Пишу со стороны разработчика, который испытал это на себе — приходится слушать доклады только ради общего развития, а не для того, чтобы бежать и внедрять себе на проект что-то новенькое. Как пример, тот же самый Vite просто так не затащить на старый проект. А это влияет от скорости сборки до комфорта самих разработчиков. Чем дольше откладываешь, тем больше будет проблем в будущем.
-
Полезности Vue 3, и это не только про новый синтаксис. В новую версию добавили много полезных вещей, исправили реактивность, добавили полезный Composition API, сделали разработку более прогнозируемой и удобной.
-
Оптимизация и скорость сборки. Vue 3 быстрее и легче: размер бандла меньше, более эффективный рендер, доработанный tree‑shaking. Для средних и крупных проектов даёт ощутимый прирост — быстрее запускается, собирается и грузится. Почти для всех проектов важна скорость загрузки и время отклика. И миграция становится уже не техническим долгом, а реальной бизнес‑задачей.
-
Привлекательнось для найма новых сотрудников. Да, с наймом сейчас сложно. Но важно смотреть на перспективу. Замотивированные разработчики стремятся идти в ногу со временем и новыми технологиями. На мой взгляд, это влияет на профессиональную привлекательность сотрудника.
Лично для меня самый важный аргумент в пользу миграции на Vue 3 — безопасность. Со всем можно работать. Но знать, что есть потенциальные дыры и создавать потенциальные риски для пользователей — сомнительная мотивация.
Возможные риски: утечка пользовательских данных, взлом аккаунта, внедрение вредоносного кода через зависимости, репутационные и финансовые потери. И это только верхушка айсберга.
Если перечисленных пунктов не достаточно, чтобы донести важность миграции на Vue 3, то есть некоторые мысли:
Скрытый текст
Предложить менеджерам не идею: «А давайте всё перепишем и заживём!». А конкретную БИЗНЕС задачу, и главное делать это ПОЭТАПНО.
Например, нужно реализовать какую‑нибудь фичу и сразу же закладывать в неё немного рефакторинга под миграцию на Vue 3. В задаче фиксируется как необходимый шаг для того, чтобы новый функционал работал корректно. Мы не проводим миграцию — а делаем бизнес‑улучшения и снижаем технический долг.
Главное — заранее выстроить план миграции: выписать все проблемные места, несовместимые API и изменения, которые предстоит внести. Когда большой объём работы разбит на понятные небольшие шаги, то миграция перестаёт выглядеть чем-то большим и страшным.
Именно здесь начинается вторая важная часть — подготовка к миграции.
Подготовка к миграции на Vue 3
Миграция большого legacy-проекта с Vue 2 на Vue 3 — это в первую очередь про анализ, планирование и организацию процесса. Основная сложность начинается ещё до первого коммита: оценить объём работы, найти несовместимые API, продумать стратегию миграции и минимизировать риски для команды и продукта.
Главная проблема миграции — не новое Vue API. Главная проблема — отсутствие процесса.
Поделюсь своим опытом, где мне пришлось лидировать миграцию: самостоятельно составлять план работ, оценивать время и риски, доносить важность перехода.
С чем пришлось работать:
-
Крупный legacy-проект UI-библиотека, который был написан частично на
render-функцияхи с повсеместным использованием$children, которые удалены во Vue 3. -
Мы решили не переходить на Composition API, а оставить Option API. Во-первых, проект будет проще мигрировать на той же структуре, во-вторых, разработчикам меньше времени потребуется на то, чтобы вникнуть в новую версию Vue 3 без доп плюшек в виде Composition API. Не надо намеренно усложнять себе жизнь, а делать всё поэтапно.
-
Два разработчика, сжатые сроки и большие ожидания успешного результата.
С чего начать подготовку
Первый шаг, которым точно не стоит пренебрегать: перевести проект на самую последнюю версию Vue 2 — 2.7.16 с обратной совместимостью. В ней уже есть многие возможности из Vue 3.
Это снижает стоимость будущей миграции и уменьшает технический долг:
-
встроенный Composition API
-
поддержка defineComponent
-
<script setup>
-
улучшенные TypeScript-типы
-
ESM/CJS совместимость ближе к Vue 3
-
обновлённые devtools и tooling expectations
-
более современная сборка через Vite/новые loaders
Важный момент, что на этом этапе мы ещё не переписываем старую функциональность на новую. Но именно с этой версии можно добавлять новые фичи с учётом новых возможностей, которые без проблем потом будут работать на API Vue 3.
И чтобы не накапливать технический долг в будущем стоит обговорить с командой и установить правила как вы будете писать новый код в продакшене, не используя устаревшие возможности Vue 2. Это важный шаг про внедрение новых процессов.
Организация parallel development
Чтобы не замораживать основную разработку и не ломать продакшен мы приняли решение процесс распараллелить: основная разработка продолжалась в developers, а миграция на Vue 3 в отдельной ветки с префиксом VUE3, которая была создана от основной developers.
Новые изменения переносились из developers через cherry-pick, после чего при необходимости сразу адаптировались под Vue 3 на основании таблицы миграции, о которой расскажу дальше.
Такой подход позволил продолжать выпускать бизнес-задачи без feature freeze, а миграцию проводить постепенно и контролируемо.
Аудит несовместимостей
Далее ВАЖНЫЕ шаги подготовки к миграции:
-
Таблица изменений Vue 2 → Vue 3. Составить таблицу всех изменений, которые предстоит сделать на проекте, которая даст возможность:
-
Оценить предстоящие работы
-
Понять риски
-
На основании этих пунктов можно планировать и создавать задачи на разработку
Для миграции есть официальная документация. Теперь эта наш главный помощник. В ней можно увидеть все изменения Vue 3 по сравнению с Vue 2.
Также документация рекомендует установить «the migration build»
@vue/compat. Но это последний шаг в подготовке к миграции. А пока нам нужна таблица совместимостей. На данном этапе мы из неё возьмём только список всех изменений. И создадим свою таблицу соответствия старых и новых API. Делюсь с вами наработками ниже.Таблица соответствий старых и новых API
Скрытый текст
Категория
Vue 2
Vue 3
Что делать / чем заменить
Создание приложения
new Vue()
createApp()
Заменить на createApp(App).mount(‘#app’)
Mount
mount заменял root element
mount НЕ заменяет container
Проверить CSS/DOM-зависимости
Global API
Vue.extend()
defineComponent()
Использовать defineComponent
Global properties
Vue.prototype.xxx
app.config.globalProperties.xxx
Перенести глобальные свойства
Reactivity
Vue.set()
не нужен
Использовать обычное присваивание
Reactivity
Vue.delete()
не нужен
Использовать delete obj.key
Reactivity
Vue.observable()
reactive()
Использовать reactive
Lifecycle
beforeDestroy
beforeUnmount
Переименовать hook
Lifecycle
destroyed
unmounted
Переименовать hook
Destroy API
$destroy()
удалён
Удалить использование
Event bus
$on/$off/$once
удалены
Использовать mitt / emitter / store
Children API
$children
удалён
Использовать refs / props
Slots
$scopedSlots
$slots
Slots теперь функции
Listeners
$listeners
merged into $attrs
Использовать $attrs
Attrs
$attrs без class/style
включает class/style
Учесть при прокидывании attrs
Data option
data мог быть object
data() всегда function
Всегда использовать function
Mixins merge
deep merge
shallow merge
Проверить mixins/extensions
Watch arrays
mutation trigger
только deep: true
Добавить deep watch
Async components
() => import()
defineAsyncComponent()
Использовать новый API
Functional SFC
<template functional>
удалён
Использовать function components
Functional components
object API
plain functions
Переписать functional components
v-model
value + input
modelValue + update:modelValue
Обновить API компонентов
.sync
:prop.sync
v-model:prop
Заменить syntax
.native
@click.native
удалён
Удалить modifier
Filters
{{ text | filter }}
удалены
Заменить на methods/computed
Custom directives
bind/inserted/unbind
beforeMount/mounted/unmounted
Переименовать hooks
Render functions
createElement(h)
h()
Обновить render API
Transition group
всегда wrapper element
wrapper отсутствует
Проверить layout/styles
Transition classes
старые классы
новые naming rules
Обновить transition classes
v-if + v-for
другой precedence
v-if выше
Разделить через template
<template v-for>
key на child
key на template
Перенести :key
inline-template
поддерживался
удалён
Удалить
is=»»
работал везде
только <component>
Использовать <component :is=»»>
v-bind=»object»
order insensitive
order sensitive
Проверить порядок attrs
KeyCode modifiers
.13, .enter
keyCode removed
Использовать key names
Config
config.keyCodes
удалён
Удалить
Config
config.productionTip
удалён
Удалить
Config
config.silent
удалён
Удалить
Custom elements
ignoredElements
compilerOptions.isCustomElement
Обновить config
Internal utils
Vue.util
private
Удалить использование
Hook events
hook:mounted
удалены
Переписать логику
Boolean attrs
false удалял attr
attr остаётся
Проверить bindings
Enumerated attrs
special coercion
убрано
Проверить attrs
Compiler filters
template filters
удалены
Переписать
Ref in v-for
старое поведение
новое поведение
Проверить refs
-
-
Аудит использования несовместимых API. После составления таблицы необходимо понять, какие из этих API реально используются в проекте и насколько часто. Я проходилась по каждому пункту, шла в редактор кода, открывала проект и смотрела, сколько раз это свойство из колонки Vue 2 встречается в коде. Например, поиск по
.extendдал такой результат:Категория
Vue 2
Vue 3
Что делать / чем заменить
Сколько раз встречается
Global API
Vue.extend()
defineComponent()
Использовать defineComponent
5
В этом примере
.extendиспользуется на проекте 5 раз. Значит нужно будет переписать наdefineComponentв 5-ти местах. Добавляем ещё одну колонку в нашу таблицу и заносим туда число совпадений. Эта информация будет важна при оценки задачи, чтобы можно было понять сколько будет изменений. -
Создание задач на разработку. По каждой строке из таблицы создаём отдельную dev-task задачу. Мы использовали Jira, но аналогичный процесс можно выстроить в любой платформе для управления разработкой. В задаче описываем, что необходимо сделать и в скольких местах. Также будет полезно приложить ссылки на репозиторий с теми компонентами, в которых надо будет заменить эту логику. В документации по миграции есть описание каждого изменения с примером.
Пример dev-task задачи в Jira на миграцию Vue.extend() → defineComponent() Мы делали так: создавали Epic в Jira по миграции Vue 3, где у нас велась вся разработка. Далее к этому эпику подвязывали все созданные задачи на миграцию из нашей таблицы изменений. Приоритет выше ставили тем, которые incompatible из таблицы с совместимостью. Важно было первоочерёдно закрыть те задачи, которые полностью ломали приложение.
Пример Epic в Jira миграции Vue 2 → Vue 3 со связанными задачами -
Задачи на исследования. Если по некоторым пунктам нет точно понимания как переписать компонент на новую логику. Например, мы столкнулись со сложностью удаления внутренних
$on/$off/$once. Не буду вдаваться в подробности, однако был legacy-код и нужно было найти более гибкое решение, чем переписать на глобальный Event bus. То мы создавали задачи на инвестигейт (исследование проблемы) и уже по результатам создавали задачку на разработку dev-task.
Пример investigation-задачи для поиска решения несовместимого legacy API -
Оценка задач и сроков. Этот этап может занять много времени, особенно на крупных legacy-проектах. Мы выделяли по 10-20 минут на общих звонках и потихоньку оценивали. В конце это даст понимание, сколько всего времени и сил потребуется. Мы оценивали в Story Points, и конечно, в таком формате точного времени мы не узнаем. Однако, нам было понятно, сколько спринтов и разработчиков на это потребуется, так как на спринт выделялось фиксированное количество Story Points.
Важно понимать: основные сложности обычно возникают не в обновлении версии пакетов, а в legacy-решениях вокруг проекта. В нашем случае больше всего проблем принесли render-functions, event bus, удаление $children, старые scoped slots и большое количество тестов, завязанных на Vue 2.
Следующие этапы
После того, как все задачи созданы, исследования проведены, ресурсы согласованы и выделены — можно будет приступать к миграции:
-
Обновиться до Vue 3 и установить
@vue/compat. После перехода на Vue 3 рекомендуется подключить миграционный плагин @vue/compat — специальный режим совместимости, который помогает запускать legacy-код и постепенно устранять несовместимости. Нужно быть готовым к тому, что часть приложения может сломаться. Однако compat позволяет сохранить работоспособность приложения во время миграции и увидеть проблемные места через warnings и runtime-ошибки в консоли. -
Обновить все плагины до доступных совместимых версий, следуя документации по миграции.
-
Переводить код на Vue 3 API по созданным задачам, постепенно устраняя compat warnings и отключая legacy-фичи через
configureCompatилиcompatConfigв соответствии с разделом Compat Configuration. -
В конце полностью удалить
@vue/compat.
Чем полезен такой подход
Преимущество этого подхода в том, что он превращает миграцию крупного legacy-проекта в набор небольших задач с понятным результатом, что упрощает планирование и снижает риски.
Сложно оценить объём работы не зная точных изменений и количества времени. Предложенное выше планирование даёт оценку того, что нужно будет сделать. Эта оценка возможно не будет на 100% точная. Но разве есть большие комплексные задачи с точной оценкой?
Помним: не надо бежать и всё сразу переписывать на Composition API. Это не будет решать основных проблем в виде уязвимостей, зато добавит больше работ при миграции и тестировании. Берём рабочий и безопасный минимум.
Выводы и мысли
И как итог, хочу поделиться мыслью. Разработчик в современных реалиях это не просто тот человек, который пишет код. Сейчас с этим неплохо справляется AI.
Разработчик — это тот, кто умеет понимать бизнес-контекст задачи, доносить важность задач на понятном бизнесу языке, принимать технические решения, оценивать риски и объём работ, планировать этапы реализации, выстраивать архитектуру, проверять гипотезы, анализировать последствия изменений и брать ответственность за общий результат, а не только за строчки кода.
Согласна, очень много всего! Однако, вся эта статья показывает, как важно уметь декомпозировать большое и сложное, на маленькое и понятной.
По сути, вся миграция на Vue 3 строилась не вокруг «переписать проект», а вокруг последовательного решения маленьких конкретных проблем.
И, наверное, это главный вывод, который я вынесла из этой миграции: большие технические изменения не происходят быстро и одним рывком. Всё становится реальными тогда, когда появляется понятный план, прозрачные процессы и ответственность (ответственный) за каждый этап.
Если после этой статьи миграция перестанет казаться чем-то хаотичным и невозможным — значит, пол дела сделано.
ссылка на оригинал статьи https://habr.com/ru/articles/1042068/