Какие сложности могут возникнуть при миграции с Vue 2 на Vue 3?

Миграция с Vue 2 на Vue 3 — это не просто обновление зависимости, а переход на новую архитектуру с изменёнными API, компилятором, реактивной системой и внутренними механизмами. В Vue 3 сохранена совместимость со многими особенностями Vue 2 через Migration Build, но полная миграция требует пересмотра подходов к разработке, особенно в больших приложениях.

Ниже перечислены сложности, которые могут возникнуть при миграции, сгруппированные по типам: технические, архитектурные, синтаксические, совместимость с зависимостями и инфраструктурные.

1. Различия в реактивной системе

Vue 2: Object.defineProperty()

  • Ограничения в обнаружении новых свойств (Vue.set(), this.$set()).

  • Проблемы с Array-методами, глубоким слежением.

Vue 3: Proxy

  • Полная поддержка глубоких и вложенных реактивных объектов.

  • Vue.set() и Vue.delete() больше не нужны.

Проблемы при миграции:

  • Старый код с Vue.set не нужен и может быть источником ошибок.

  • Object.freeze делает объект нереактивным в Vue 3.

  • Использование isReactive() / isRef() становится необходимым при работе с внешними библиотеками.

2. API изменения в core

Удалённые/изменённые API:

  • this.$on, this.$off, this.$once — удалены, нужно использовать emits и mitt.

  • keyCode в v-on — больше не поддерживается (@keyup.enter вместо @keyup.13).

  • v-model работает иначе: один modelValue + update:modelValue, больше не value + @input.

<!-- Vue 2 -->
<input :value="value" @input="$emit('input', $event)" />
<!-- Vue 3 -->
<template>
<input :value="modelValue" @input="$emit('update:modelValue', $event)" />
</template>

3. Изменения жизненного цикла

Старые хуки:

  • beforeDestroy, destroyed

Новые имена:

  • beforeUnmount, unmounted

Проблемы:

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

  • Некоторые библиотеки всё ещё используют устаревшие хуки и требуют патчей.

4. Composition API

Vue 3 добавил новую модель через setup() и ref, reactive, computed, watch, и т.д.

Сложности:

  • Переход на Composition API требует полной переработки логики компонентов.

  • Старый Options API продолжает поддерживаться, но при смешивании возникают конфликты типов и тестируемости.

  • Инструменты (eslint, typescript) требуют настройки под setup()-синтаксис.

5. Изменения в директивах

  • v-bind.sync удалён.

  • v-model теперь может быть мультиэкземплярным (с разными аргументами): v-model:title, v-model:checked.

  • v-if и v-for на одном элементе теперь требуют обёртки.

6. Шаблонные особенности

  • v-on.native удалён.

  • Функциональные компоненты должны использовать defineComponent({ functional: true }) больше не поддерживается.

  • $listeners, $attrs, $slots теперь обрабатываются иначе.

7. Обновление зависимости от Vue CLI / Webpack

  • Vue 3 больше не поддерживает старый vue-cli (v4 и ниже).

  • Требуется @vue/cli >= 5 или переход на Vite.

  • Обновление babel, eslint, postcss, typescript, vue-loader, sass-loader, vue-jest — требует ручной настройки.

  • В Vue 3 используется @vue/compiler-sfc, не совместимый с .vue файловой структурой Vue 2.

8. Сторонние библиотеки

Часто несовместимы:

  • vuex@3 не работает с Vue 3 → требуется vuex@4 или pinia.

  • vue-router@3 не работает с Vue 3 → нужен vue-router@4.

  • vuetify@2 — только для Vue 2 → нужен vuetify@3.

  • Старые UI-библиотеки (element-ui, buefy, bootstrap-vue) не обновляются под Vue 3.

  • vee-validate, vue-i18n, axios, vue-test-utils, vue-apollo требуют Vue 3-совместимых версий.

Проблема:

  • Некоторые библиотеки не имеют Vue 3 версии — требуется заменить или отказаться.

9. Тестирование и devtools

  • @vue/test-utils@1 — несовместим с Vue 3 → перейти на @vue/test-utils@2.

  • Старые snapshot-тесты ломаются из-за разных шаблонных рендеров.

  • Vue Devtools для Vue 2 и Vue 3 — разные, требуются соответствующие расширения.

10. SSR

Изменения:

  • Vue 3 имеет совершенно новый SSR API.

  • Vue 2 использовал vue-server-renderer, который несовместим с Vue 3.

  • Требуется @vue/server-renderer + ручное создание context + stream поддержка.

11. TypeScript и декларации

  • Vue 3 написан на TypeScript и требует корректных типов.

  • В Vue 2 многие типы были "any", в Vue 3 строже.

  • Ошибки компиляции появляются даже в шаблонах, если lang="ts" не согласован с defineComponent.

12. Рефакторинг компонентов

  • Компоненты с mixins становятся сложнее при переносе на Composition API.

  • extends, inheritAttrs, provide/inject требуют пересмотра.

13. Migration Build и runtime warnings

Vue предоставляет специальную "migration build", в которой старый API работает, но выдаёт предупреждения в консоли.

Проблемы:

  • Не работает в production.

  • Некоторые API всё равно не включены (например, .sync, native).

  • Только временное решение для поэтапной миграции.

14. Миграция шаблонов

  • Старые шаблоны могут использовать устаревшие конструкции, например:

    • v-bind.sync="..." → надо переписать вручную.

    • keyCode → надо заменить на alias (enter, esc).

    • scopedSlots → теперь только slots.

15. Разделение на модули и tree-shaking

Vue 3 использует ESM и tree-shaking, что требует:

  • Обновления сборщика (Webpack 5, Vite).

  • Отказа от require() в пользу import.

  • Настройки babel, tsconfig.json и vite.config.ts.

16. Управление глобальными компонентами и плагинами

  • Vue.use() больше не работает — плагины должны быть функцией с app.use(plugin).

  • Глобальные компоненты надо регистрировать вручную в main.ts:

app.component('MyComponent', MyComponent);

17. Сложности при поддержке гибридного проекта (Vue 2 + Vue 3)

  • Комбинация несовместима без использования iframe или micro-frontends.

  • Разные версии vue-loader, babel, eslint, devtools.

  • Возможно дублирование кода и увеличение бандла.

18. Поддержка старого браузера IE11

  • Vue 3 не поддерживает Internet Explorer.

  • При необходимости поддержки IE11 нужно оставаться на Vue 2 или использовать транспиляцию + полифиллы (не рекомендуется).

19. Обратная совместимость unit/functional компонентов

  • functional: true больше не поддерживается в defineComponent().

  • Требуется переписывать такие компоненты вручную.

20. Влияние на производительность и bundle

  • Vue 3 быстрее и легче, но при миграции возможен временный рост размера бандла из-за дублирующих зависимостей (vue@2 + vue@3, если неаккуратно выполнен переход).

  • Старые зависимости могут требовать форков или удаления.