# Сборка для миграции
# Обзор
@vue/compat
(она же «сборка для миграции») — специальная сборка Vue 3, поведение которой можно настраивать для совместимости с Vue 2.
Сборка для миграции по умолчанию работает в режиме Vue 2 — большая часть публичных API ведёт себя точно также, как и во Vue 2, за несколькими исключениями. Использование возможностей, которые претерпели изменения или объявлены устаревшими во Vue 3, будут выбрасывать предупреждения во время выполнения. Также есть возможность включать и выключать на уровне компонента совместимость с определёнными возможностями.
# Предполагаемые сценарии использования
- Обновление приложения Vue 2 на Vue 3 (с некоторыми ограничениями)
- Миграция библиотеки для поддержки Vue 3
- Для опытных разработчиков Vue 2, которые ещё не пробовали Vue 3, сборка для миграции может помочь в изучении различий между версиями.
# Известные ограничения
Несмотря на то, что сборка для миграции реализовывалась максимально похожей поведением на Vue 2, есть некоторые ограничения, которые могут препятствовать обновлению приложения:
Зависимости, полагающиеся на внутренние API Vue 2 или недокументированное поведение. Наиболее частым случаем является использование приватных свойств на
VNodes
. Если проект полагается на библиотеки компонентов, такие как Vuetify (opens new window), Quasar (opens new window) или ElementUI (opens new window), то сначала лучше дождаться их новых версий, совместимых с Vue 3.Поддержка Internet Explorer 11: Vue 3 официально отказался от поддержки IE11 (opens new window). При необходимости поддерживать IE11 или ниже придётся остаться на Vue 2.
Отрисовка на стороне сервера (SSR): сборку для миграции можно использовать для SSR, но миграция пользовательской конфигурации SSR задача намного сложнее. В общем, идея заключается в замене
vue-server-renderer
на@vue/server-renderer
(opens new window). Vue 3 больше не предоставляет bundle renderer и рекомендуется использовать Vue 3 SSR с Vite (opens new window). Если в проекте используется Nuxt.js (opens new window), то можно попробовать Nuxt Bridge, слой совместимости Nuxt.js 2 и 3 (opens new window). Для более сложных проектов, лучше дождаться Nuxt 3 (в настоящее время в бета) (opens new window).
# Ожидания
Обратите внимание, сборка для миграции нацелена лишь на публично документированные API и поведение Vue 2. Если приложение не будет работать со сборкой для миграции из-за использования недокументированного поведения, маловероятно, что изменим сборку для миграции, чтобы удовлетворить подобный конкретный случай. Вместо этого рассмотрите возможность рефакторинга, чтобы избавиться от данного нестандартного поведения.
Предостережение: для большого и сложного приложения миграция, скорее всего, будет сложной даже со сборкой для миграции. Если приложение не подходит для обновления, обратите внимание, что планируется портировать Composition API и некоторые другие функции Vue 3 в релизе 2.7 (предположительно в конце третьего квартала 2021).
Если приложение на сборке для миграции удалось запустить, то его можно опубликовать в production до завершения процесса миграции. Несмотря на небольшие накладные расходы по производительности/размеру, это не должно заметно повлиять на UX в production. Такое может потребоваться, если есть зависимости, которые зависят от поведения Vue 2, и не могут быть обновлены/заменены.
Сборка для миграции выпускается, начиная с версии 3.1, и будет продолжать обновляться вместе с релизами 3.2. Публикация обновлений сборки для миграции будет прекращена в одной из будущих минорных версий (не ранее конца 2021 года), поэтому до этого времени стоит запланировать переход на стандартную сборку.
# Процесс обновления
Следующий процесс обновления описывает шаги по миграции фактического приложения на Vue 2 (Vue HackerNews 2.0) до Vue 3. Полный список коммитов можно найти здесь (opens new window). Обратите внимание, что для собственного проекта фактические шаги могут отличаться. Описанную здесь последовательность следует рассматривать как общее руководство к действию, а не как строгую инструкцию.
# Подготовка
- При использовании устаревшего синтаксиса именованных слотов / слотов с ограниченной областью видимости (opens new window), обновите его сначала до нового синтаксиса (который уже поддерживается в версии 2.6).
# Установка
Обновите инструментарий, при возможности.
- При использовании пользовательской конфигурации webpack: обновите
vue-loader
до версии^16.0.0
. - При использовании
vue-cli
: обновите@vue/cli-service
до последней версии с помощью командыvue upgrade
- (Альтернатива) Мигрируйте на Vite (opens new window) + vite-plugin-vue2 (opens new window). [Пример коммита (opens new window)]
- При использовании пользовательской конфигурации webpack: обновите
В файле
package.json
, обновитеvue
до 3.1. Установите@vue/compat
такой же версии и заменитеvue-template-compiler
(если присутствует) на@vue/compiler-sfc
:"dependencies": { - "vue": "^2.6.12", + "vue": "^3.1.0", + "@vue/compat": "^3.1.0" ... }, "devDependencies": { - "vue-template-compiler": "^2.6.12" + "@vue/compiler-sfc": "^3.1.0" }
1
2
3
4
5
6
7
8
9
10В конфигурации сборки установите псевдоним для
vue
на@vue/compat
и включите режим совместимости сборки для миграции через опции компилятора Vue.Примеры конфигураций
vue-cli
// vue.config.js module.exports = { chainWebpack: config => { config.resolve.alias.set('vue', '@vue/compat') config.module .rule('vue') .use('vue-loader') .tap(options => { return { ...options, compilerOptions: { compatConfig: { MODE: 2 } } } }) } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20Чистый webpack
// webpack.config.js module.exports = { resolve: { alias: { vue: '@vue/compat' } }, module: { rules: [ { test: /\.vue$/, loader: 'vue-loader', options: { compilerOptions: { compatConfig: { MODE: 2 } } } } ] } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23Vite
// vite.config.js export default { resolve: { alias: { vue: '@vue/compat' } }, plugins: [ vue({ template: { compilerOptions: { compatConfig: { MODE: 2 } } } }) ] }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19При использовании TypeScript нужно изменить типизацию
vue
для объявления экспорта по умолчанию (которого больше нет во Vue 3), добавив*.d.ts
следующего вида:declare module 'vue' { import { CompatVue } from '@vue/runtime-dom' const Vue: CompatVue export default Vue export * from '@vue/runtime-dom' }
1
2
3
4
5
6На данном этапе приложение может столкнуться с ошибками / предупреждениями на этапе компиляции (например, при использовании фильтров). Исправьте их в первую очередь. После того как все предупреждения компилятора будут исправлены, можно переключить компилятор в режим Vue 3.
После исправления ошибок приложение должно запускаться, если его не затрагивают известные ограничения, перечисленные выше.
Скорее всего увидите МНОЖЕСТВО предупреждений, как в командной строке, так и в консоли браузера. Вот несколько общих советов:
Можно отфильтровать конкретные предупреждения в консоли браузера. Хорошая идея — воспользоваться фильтром и сосредоточиться на исправлении одного типа ошибки за раз. Также можно использовать отрицание в фильтрах, например
-GLOBAL_MOUNT
.Можно отключить вывод предупреждений о конкретных ошибках через конфигурацию совместимости.
Некоторые предупреждения могут быть вызваны используемой зависимостью (например,
vue-router
). Проверить это можно по трассировке предупреждения компонента или трассировке стека (разворачивается по клику). Для начала лучше сосредоточиться на исправлении предупреждений в собственном исходным коде.Если используете
vue-router
, обратите внимание, что<transition>
и<keep-alive>
не будут работать с<router-view>
пока не обновитеvue-router
до версии v4.
Обновите имена классов
<transition>
. Это единственная функция, которая не имеет предупреждения во время выполнения. Можно выполнить поиск по всему проекту для имён CSS-классов.*-enter
и.*-leave
.Обновите точку входа приложения на использование нового глобального API монтирования.
Обновите
vue-router
до версии v4 (opens new window). Если также используетсяvuex-router-sync
, то можно его заменить на геттер.После обновления, для использования
<transition>
и<keep-alive>
совместно с<router-view>
необходимо воспользоваться новым синтаксисом слотов с ограниченной областью видимости (opens new window).Выбирайте отдельные предупреждения и исправляйте их. Обратите внимание, что некоторые функции имеют несовместимое поведение между Vue 2 и Vue 3 — например, API render-функций или изменения функциональных компонентов vs. асинхронных компонентов. Чтобы выполнять миграцию на API Vue 3, не затрагивая остальные части приложения, можно определять поведение Vue 3 для конкретного компонента через опцию
compatConfig
.После исправления всех предупреждений можно удалить сборку для миграции и перейти на обычную сборку Vue 3. Обратите внимание, что это нельзя будет сделать, если есть зависимости, которые полагаются на поведение Vue 2.
# Конфигурация совместимости
# Глобальная конфигурация
Совместимость с возможностями можно отключать по-отдельности:
import { configureCompat } from 'vue'
// отключение совместимости для отдельных возможностей
configureCompat({
FEATURE_ID_A: false,
FEATURE_ID_B: false
})
2
3
4
5
6
7
В качестве альтернативы, всё приложение может по умолчанию использовать поведение Vue 3, включая совместимость лишь для определённых возможностей:
import { configureCompat } from 'vue'
// по умолчанию всё поведение как во Vue 3, и только
// включение совместимости для определённых возможностей
configureCompat({
MODE: 3,
FEATURE_ID_A: true,
FEATURE_ID_B: true
})
2
3
4
5
6
7
8
9
# Конфигурация для компонента
В компоненте можно использовать опцию compatConfig
, которая ожидает такие же параметры, что и глобальный метод configureCompat
:
export default {
compatConfig: {
MODE: 3, // выбор поведения Vue 3 для этого компонента
FEATURE_ID_A: true // возможностями можно управлять на уровне компонента
}
// ...
}
2
3
4
5
6
7
# Конфигурация компиляции
Возможности, названные с COMPILER_
, специфичны для компилятора: при использовании полной сборки (с компиляцией шаблонов в браузере), они могут быть настроены во время выполнения. Однако при использовании шага сборки их нужно настраивать через опцию compilerOptions
в конфигурации сборки (см. примеры конфигураций выше).
# Перечень возможностей
# Типы совместимости
- ✔ Полная совместимость
- ◐ Частичная совместимость (с ограничениями)
- ⨂ Нет совместимости (только предупреждения)
- ⭘ Только для совместимости (нет предупреждений)
# Нет совместимости
Требуется исправить заранее или может приводить к ошибкам
ID | Тип | Описание | Документация |
---|---|---|---|
GLOBAL_MOUNT_CONTAINER | ⨂ | Монтируемое приложение не заменяет элемент, к которому монтируется | ссылка |
CONFIG_DEVTOOLS | ⨂ | devtools в production теперь определяется флагом при сборке | ссылка (opens new window) |
COMPILER_V_IF_V_FOR_PRECEDENCE | ⨂ | приоритет v-if и v-for при использовании на одном и том же элементе изменился | ссылка |
COMPILER_V_IF_SAME_KEY | ⨂ | ветви v-if больше не могут иметь одинаковый key | ссылка |
COMPILER_V_FOR_TEMPLATE_KEY_PLACEMENT | ⨂ | для <template v-for> указывать key теперь нужно на <template> | ссылка |
COMPILER_SFC_FUNCTIONAL | ⨂ | <template functional> больше не поддерживается в однофайловых компонентах | ссылка |
# Частичная совместимость (с ограничениями)
ID | Тип | Описание | Документация |
---|---|---|---|
CONFIG_IGNORED_ELEMENTS | ◐ | config.ignoredElements теперь является config.compilerOptions.isCustomElement (только в сборке с компилятором в браузере). При использовании шага сборки, isCustomElement должен передаваться через конфигурацию сборки. | ссылка |
COMPILER_INLINE_TEMPLATE | ◐ | inline-template удалён (поддерживается только совместимость в сборке с компилятором шаблонов) | ссылка |
PROPS_DEFAULT_THIS | ◐ | фабрика значения по умолчанию входного параметра больше не имеет доступа к this (в режиме совместимости this не является реальным экземпляром — он только предоставляет доступ к входным параметрам, $options и внедрённым свойствам) | ссылка |
INSTANCE_DESTROY | ◐ | удалён метод экземпляра $destroy (в режиме совместимости поддерживается только для корневого экземпляра) | |
GLOBAL_PRIVATE_UTIL | ◐ | Vue.util является приватным и больше недоступно | |
CONFIG_PRODUCTION_TIP | ◐ | config.productionTip больше не нужен | ссылка |
CONFIG_SILENT | ◐ | config.silent удалён |
# Только для совместимости (нет предупреждений)
ID | Тип | Описание | Документация |
---|---|---|---|
TRANSITION_CLASSES | ⭘ | Изменены классы переходов enter/leave | ссылка |
# Полная совместимость
ID | Тип | Описание | Документация |
---|---|---|---|
GLOBAL_MOUNT | ✔ | new Vue() -> createApp | ссылка |
GLOBAL_EXTEND | ✔ | Vue.extend удалён (используйте defineComponent или опцию extends ) | ссылка |
GLOBAL_PROTOTYPE | ✔ | Vue.prototype -> app.config.globalProperties | ссылка |
GLOBAL_SET | ✔ | Vue.set удалён (больше не нужен) | |
GLOBAL_DELETE | ✔ | Vue.delete удалён (больше не нужен) | |
GLOBAL_OBSERVABLE | ✔ | Vue.observable удалён (используйте reactive ) | ссылка |
CONFIG_KEY_CODES | ✔ | config.keyCodes удалён | ссылка |
CONFIG_WHITESPACE | ✔ | Во Vue 3 пробельные символы по умолчанию "condense" | |
INSTANCE_SET | ✔ | vm.$set удалён (больше не нужен) | |
INSTANCE_DELETE | ✔ | vm.$delete удалён (больше не нужен) | |
INSTANCE_EVENT_EMITTER | ✔ | vm.$on , vm.$off , vm.$once удалены | ссылка |
INSTANCE_EVENT_HOOKS | ✔ | Экземпляр больше не генерирует события hook:x | ссылка |
INSTANCE_CHILDREN | ✔ | vm.$children удалён | ссылка |
INSTANCE_LISTENERS | ✔ | vm.$listeners удалён | ссылка |
INSTANCE_SCOPED_SLOTS | ✔ | vm.$scopedSlots удалён; vm.$slots теперь предоставляет доступ к функциям | ссылка |
INSTANCE_ATTRS_CLASS_STYLE | ✔ | $attrs теперь содержит class и style | ссылка |
OPTIONS_DATA_FN | ✔ | data должна быть функцией во всех случаях | ссылка |
OPTIONS_DATA_MERGE | ✔ | data из примеси или расширения теперь неглубоко объединяются | ссылка |
OPTIONS_BEFORE_DESTROY | ✔ | beforeDestroy -> beforeUnmount | |
OPTIONS_DESTROYED | ✔ | destroyed -> unmounted | |
WATCH_ARRAY | ✔ | Отслеживание массива больше не срабатывает при мутации без deep | ссылка |
V_FOR_REF | ✔ | ref внутри v-for не регистрирует массив refs | ссылка |
V_ON_KEYCODE_MODIFIER | ✔ | v-on больше не поддерживает модификаторы keyCode | ссылка |
CUSTOM_DIR | ✔ | Имена хуков пользовательских директив изменены | ссылка |
ATTR_FALSE_VALUE | ✔ | Атрибут больше не удаляется при привязке булево значения false | ссылка |
ATTR_ENUMERATED_COERCION | ✔ | Перечисляемые атрибуты больше не являются особым случаем | ссылка |
TRANSITION_GROUP_ROOT | ✔ | <transition-group> не отрисовывает корневой элемент по умолчанию | ссылка |
COMPONENT_ASYNC | ✔ | API асинхронных компонентов изменено (теперь требуется defineAsyncComponent ) | ссылка |
COMPONENT_FUNCTIONAL | ✔ | API функциональных компонентов изменено (должны быть обычными функциями) | ссылка |
COMPONENT_V_MODEL | ✔ | Переработана v-model на компонентах | ссылка |
RENDER_FUNCTION | ✔ | API render-функций изменено | ссылка |
FILTERS | ✔ | Фильтры удалены (эта опция влияет только на API фильтров во время выполнения) | ссылка |
COMPILER_IS_ON_ELEMENT | ✔ | Использование is теперь ограничено только <component> | ссылка |
COMPILER_V_BIND_SYNC | ✔ | v-bind.sync заменяется v-model с аргументами | ссылка |
COMPILER_V_BIND_PROP | ✔ | Удалён модификатор v-bind.prop | |
COMPILER_V_BIND_OBJECT_ORDER | ✔ | v-bind="object" is now order sensitive | ссылка |
COMPILER_V_ON_NATIVE | ✔ | Удалён модификатор v-on.native | ссылка |
COMPILER_V_FOR_REF | ✔ | ref в v-for (поддержка компилятора) | |
COMPILER_NATIVE_TEMPLATE | ✔ | <template> без специальных директив теперь отрисовывается как нативный элемент | |
COMPILER_FILTERS | ✔ | Фильтры (поддержка компилятора) |