Здравствуйте! В данной статье я бы хотел поделиться своим опытом обновления проекта, написанного на Vue 2.6. Помимо обновления самого vue и компонентов, я на примерах покажу как мне удалось обновить другие зависимости проекта и адаптировать их для работы с Composition API, среди них: Vuex, BootstrapVue, AgGrid и VueFormGenerator. Как ни странно, но данному нововведению мы обязаны React-у, а точнее представленной в 2018 году концепции react-хуков. Я никогда не трогал React, лишь бегло прочитал его документацию, поэтому не могу объективно высказаться об этой возможности библиотеки, однако почти все React-разработчики заявляют что хуки позволяют в значительной мере упростить разработку и создавать переиспользуемый код; более того функциональные компоненты с использованием хуков это уже стандарт разработки на React. С выходом vue 3-ей версии, разработчикам стал доступен новый подход к созданию компонентов, схожий с функциональными компонентами реакта - Composition API: метод setup и <script setup> для использования в однофайловых компонентах. Сравнивая composition API с options API, в качестве его преимуществ обычно перечисляют: простота и лаконичность  возможность создавать переиспользуемые куски логики (вместо миксинов) улучшенная поддержка TypeScrit большая производительность (по заявлениям создателей) Стоит также учесть и критические оценки такого подхода: Composition API во Vue 3 — плюсы, минусы и опыт использования Обзор Vue Composition API. Реальность оказалась сложнее В целом можно заметить что все недостатки или опасения по поводу использования composition API упираются в опыт и знания разработчика: composition API предоставляет гораздо больше инструментов для работы с реактивностью, что естественно требует некоторых усилий для понимания и осторожности, особенно если разработчик привык к options или class API. В июле 2022 года вышел релиз vue 2.7, в котором composition API было добавлено из коробки (ранее для этого требовалась библиотека @vue/composition-api), и добавлена возможность использовать <script setup>. И несмотря на то, что vue 2.6 уже официально не поддерживается, а поддержка vue 2.7 прекратится в декабре 2023 года, библиотеки на vue 2, судя по данным с npm до сих пор очень часто скачиваются и используются. Из этого следует что миграция на vue 3 прошла не совсем безболезненно, а некоторые библиотеки (например bootstrap-vue) до сих пор не портированы на vue 3. Также стоит учесть что vue 3 использует систему реактивности основанную на Proxy, которые не поддерживаются старыми браузерами. Поэтому vue 2.7, на мой взгляд, это относительно безболезненный способ использовать основную фичу vue 3 - Composition API, в своих приложениях, не переписывая при этом абсолютно весь код и не переходя на другие библиотеки. В нашей компании не раз поднимался вопрос о переходе на vue 3, однако основная библиотека для наших интерфейсов - bootstrap-vue всё ещё стабильно существует только для vue 2-ой версии. С версии 2.23.0 в bootstrap-vue доступен так называемый билд миграции. Я попробовал запустить пример проекта на bootstrap-vue и @vue/compat от самих разработчиков, и получил целый список предупреждений от vue. Это одна из причин почему я не стал использовать bootstrap-vue в compat режиме, другая же причина: migration build нужен всё же для миграции проекта, то есть постепенной замены его модулей и переписывания на vue 3, но не для разработки новых продуктов на нём. Спустя пол года полноценного релиза bootstrap-vue для vue 3 так и нет, а разрабатывать и поддерживать проекты надо. Для поддержки typescript во vue 2 команда разработчиков vue создала библиотеку vue-class-component. А с использованием библиотеки vue-property-decorator, можно в декораторном стиле объявлять пропсы, рефы и эмиты и типизировать их. Однако у Class API есть ряд существенных недостатков, о которых писал сам Эван Ю: Он не достигает своей основной цели (лучшая поддержка TypeScript)  Усложняет внутреннюю реализацию  Не приносит улучшений в логическую композицию От себя ещё добавлю: компоненты - это не классы. Это довольно субъективно, но мне кажется что мы обманываем себя когда называем компонент классом, потому что большинство правил и паттерннов ООП просто не получится применить к ним. Также для того чтобы добиться типизации приходится писать очень много лишнего кода, вот пример хранилища с использованием VuexSmartModule.  Страшновато не правда ли? Чуть дальше покажу как это выглядит на pinia. Во vue-class-component есть ещё одна ловушка, this на этапе создания класса это не тот же this, что и в компоненте, всё потому что наш класс сначала из класса преобразуется в объект понятный для vue и только после этого создаётся компонент, можете проверить это следующим образом: Получите следующую картину:constructor: true created: false Это относится и к функциям в объектах, объявленным в классе, вы просто не имеете доступ к актуальному состоянию объекта (this в данном случае всё ещё тот объект полученный из класса).  Поэтому в таких случаях приходилось создавать отдельный метод в классе и передавать уже его, даже если требовалось просто изменить какое-то одно поле в объекте, или что-то сэмитить. Однако до vue 2.7 внутри объектов можно было обращаться к пропсам и сторам (если смаппить их в methods). До появления composition API единственным способом создать переиспользуемую логику компонентов были миксины, у них есть существенные недостатки: Пересечение пространств имён Сложность типизации Непрозрачность требований (например если миксин требует наличия определённых пропсов или методов у компонента) Сложность понимания и отладки: когда вы обращаетесь ко всем методам и объектам через this, может быть затруднительно понять откуда он взялся: из самого объекта, из стора или из какого-то миксина. Только в одном случае миксины могут дать некоторое преимущество: если требуется создать переиспользуемые пропсы/эмиты, вот тут решение с composable будет слегка сложнее,  далее я покажу эту проблему на примере библиотеки vue-form-generator. В первую очередь я обновил сам vue до версии 2.7, и сразу у меня перестала работать часть компонентов, в которых использовались пропсы при объявлении внутренних объектов, как в примере выше. Я решил сразу переписать такие компоненты на composition API, но можно и попробовать забирать нужные пропсы в хуках жизненного цикла. На очереди хранилище, в целом тут не возникло особых сложностей, я подключил pinia и постепенно переписал все модули vuex. Если вы тоже использовали VuexSmartModule и не хотите переписывать все компоненты, то pinia сторы тоже можно смаппить следующим образом: Для сравнения покажу вышеописанный стор для тостов, теперь уже на pinia.  Единственной проблемой стала необходимость доступа к сторам в роутере, а точнее в нашем проекте для запуска приложения использовался следующий кусок кода: То есть до начала работы приложения требовалось получить данные пользователя для использования их в роутере. Возможно правильнее было бы вынести загрузку пользователя в middleware роутера, но оказалось что у нас много где данные хранилищ используются ещё и в redirect хуках роутера, которые не могут быть асинхронными, соответственно там загружать данные не получится. В функцию подключения хранилищ можно опционально передать инстанс самой pinia, как раз для таких случаев: Соответственно после этого мы получим доступ ко всем сторам. В целом работа с данной библиотекой не изменилась, а чтобы получить доступ к объектам $bvToast и $bvModal в <script setup> я создал простые composable AgGrid это очень мощная и одна из самых популярных библиотек для работы с таблицами, в наших проектах она широко используется. После её обновления я столкнулся с некоторыми deprecated ворнингами. Однако, если следовать тому что в них написано, то можно всё корректно обновить без особых изменений, в основном это просто другие названия для полей в объектах настроек. Но я обнаружил одну проблему, скорее всего баг самой библиотеки (на момент написания статьи она все ещё не устранена, но issue я уже отправил). Если вы в column-defs объявляете колонку с собственным рендерером (компонентом), например так: Скорее всего у вас будет что-то подобное  При этом забавно, но если написать вместо cellRenderer - cellRendererFramework, то вы получите deprecated ворнинг от библиотеки, но всё будет работать. Можно было бы попробовать передать в cellRenderer строку вместо компонента, но это тоже не получится, так как в <scirpt setup> импортированные компоненты не регистрируются. Для этого я создал ещё один <script>, где уже в options API зарегистрировал нужный компонент. Также зарегистрировать компонент можно в более императивном стиле, добавив нужный компонент по ключу-имени к соответствующему полю инстанса текущего компонента Это можно обернуть в некоторый composable который принимает объект компонента и возвращает его зарегистрированное имя:  VueFormGenerator - небольшая библиотека для генерации форм с помощью JSON схем, она больше не поддерживается разработчиками и в целом мне не очень нравится, но выкинуть из проектов её пока что не получилось, так как на ней у нас сделаны все формы. Для её адаптации к composition API пришлось сделать громоздкий composable на основе их миксина abstractField, а для переиспользования пропсов и эмитов я сделал объекты, передаваемые в defineProps и defineEmits. Кода там много, поэтому просто оставлю ссылку на gist.  Простейшее кастомное поле (обычный лэйбл) с использованием данного composable: Несмотря на все сложности, которые пришлось преодолеть, на данный момент моё мнение однозначно: оно того стоило, мы получили гораздо более компактный, понятный, более поддерживаемый код, при этом не потеряв типизацию. Особым приятным бонусом стала возможность использовать библиотеку VueUse, с помощью которой например получилось заменить стор для размера окна и миксин для отслеживания изменения его размера, всего одной функцией useWindowSize. Чуть больше про сам процесс миграции можете прочитать в этой статье.