Migrate every Vue 2 app to Vue 3.
For each repository:
1. Update `package.json`:
- `vue` to `^3.4.0`
- `vue-router` to `^4.x`, `vuex` to `^4.x` (or migrate to `pinia`; see step 5)
- Replace `@vue/cli-*` with Vite (`vite`, `@vitejs/plugin-vue`) where the build
tool is being modernized
- Bump TypeScript Vue tooling: `vue-tsc`, `@vue/tsconfig`
2. Rewrite the app bootstrap:
- `new Vue({ render: h => h(App) }).$mount('#app')` →
`createApp(App).use(router).use(pinia).mount('#app')`
- Move global plugins/directives from `Vue.use(...)` / `Vue.directive(...)` to
`app.use(...)` / `app.directive(...)`
3. Apply breaking-change rewrites:
- `v-model` on custom components: `value`/`input` → `modelValue`/`update:modelValue`
- Functional components rewritten as regular components (or use the new functional
syntax)
- Filters removed; replace with computed properties or methods
- `$listeners` merged into `$attrs`
- `$on` / `$off` / `$once` removed; use a dedicated event bus (mitt) only if necessary
4. Update slot syntax: `slot="name"` and `slot-scope` → `v-slot:name`.
5. Migrate Vuex stores to Pinia where the codebase is greenfield enough; otherwise
keep Vuex 4 and flag for a follow-up.
6. Update CI Node version to 20.x. The Problem
Vue 2 reached end of life at the end of 2023. Every Vue 2 app in the org is now on an unsupported runtime with no security patches, blocked from current versions of every Vue-ecosystem package, `vue-router`, `vuex`/`pinia`, `vue-tsc`, `@vue/test-utils`, every component library. The upgrade to Vue 3 isn't a version bump; it's a rewrite of the app bootstrap, every `v-model` on a custom component, every filter, every `$on`/`$off`/`$once` usage, and every global plugin registration.
The build-tool story makes it harder. Most Vue 2 apps were generated by `@vue/cli` on top of Webpack 4; Vue 3 apps are typically Vite-based. Migrating both at once (runtime and build toolchain) is the realistic path, but it doubles the per-repo scope. Across a UI org with thirty Vue frontends, each with its own component library, its own Vuex stores, and its own custom directives, manual migration takes months per app. The result is most orgs end up with a permanent Vue 2 long tail they can never decommission.
What Tidra Does
- Bumps
vueto^3.4,vue-routerto^4.x, and either keepsvuex@4or migrates to Pinia based on the prompt - Replaces
@vue/cli-*tooling with Vite (vite,@vitejs/plugin-vue) where the build chain is being modernised - Rewrites the app bootstrap,
new Vue({ render: h => h(App) }).$mount('#app')→createApp(App).use(router).use(pinia).mount('#app') - Applies Vue 3 breaking-change rewrites, custom-component
v-model(value/input→modelValue/update:modelValue), filter removal,$listenersmerge into$attrs, removal of$on/$off/$once - Updates slot syntax from
slot="name"/slot-scopetov-slot:name - Bumps CI Node version to 20.x and opens a PR per repo summarising the migration and any Vuex stores flagged for follow-up Pinia conversion
Before & After
Customization Tips
- Build tool decision: Decide up front whether to keep Webpack 4/5 with
@vue/clior move to Vite as part of the migration. Combining both changes is faster overall but produces a larger per-repo diff. - Vuex vs Pinia: For apps with deep Vuex usage and custom plugins, keep Vuex 4 and migrate to Pinia in a follow-up. For thin Vuex usage, fold the Pinia migration into this initiative.
- Component library compatibility: Confirm your design system or component library (Vuetify, Element Plus, Naive UI) has a Vue 3-compatible release. Vuetify 2 → 3 is itself a significant migration.
- Test coverage gate: Run
vue-tsc --noEmitand the existing unit-test suite per repo before merging. Type errors from Vue 3's stricter prop typing catch real bugs that pass at runtime.