Still on Vue 2 or Nuxt 2? What breaks, what decides the effort, and how to migrate
Vue 2 and Nuxt 2 are past end of life. A practical guide for teams and owners on the risk of staying, what breaks when you upgrade, and a migration plan that keeps the app shipping.
By Mukesh Pensia, Vue.js & Nuxt developerYour framework stopped getting fixes
Vue 2 and Nuxt 2 have both reached end of life. Neither gets new features, bug fixes or security patches anymore. Your app keeps running, but the risk grows every month. It shows up in three places:
- Security. A new vulnerability in Vue 2, Nuxt 2 or their dependencies will not be patched upstream. Security audits and enterprise customers increasingly flag it.
- Dependencies. Libraries drop Vue 2 support one by one. Sooner or later a routine update forces you to pin old versions, or a browser change breaks something nobody can fix.
- Hiring and speed. New Vue developers learn Vue 3 and the Composition API. Each feature on an old stack takes longer, and fewer people want to work on it.
Paid extended support buys time with security patches, but it is a bridge, not a destination.
Go straight to Nuxt 4
Nuxt 3 has also reached end of life. If you are leaving Nuxt 2 now, target Nuxt 4 directly. The jump is not much bigger, because most of the work is the Vue 2 → Vue 3 change underneath, and that is the same either way. Plain Vue 2 apps move to the latest Vue 3 and Vite.
What breaks
Most of the effort sits in a short list of changes. Audit your code for each before planning.
| Area | Vue 2 / Nuxt 2 | Vue 3 / Nuxt 4 |
|---|---|---|
| State | Vuex, store/ directory | Pinia (useState for small shared state) |
| Data fetching | asyncData(), fetch() hooks | useAsyncData, useFetch, $fetch |
| HTTP client | @nuxtjs/axios | $fetch (ofetch), built in |
| Head and SEO | head() option | useHead, useSeoMeta |
| Plugins and middleware | export default (ctx, inject) | defineNuxtPlugin, defineNuxtRouteMiddleware |
| Server code | serverMiddleware | server/api and server/routes (Nitro) |
| Build | webpack | Vite |
| Event bus | $on, $off, $once | Removed; use a small emitter such as mitt, or Pinia |
| Filters | {{ price | currency }} | Removed; use functions or computed values |
v-model on components | value + input | modelValue + update:modelValue |
$listeners, .native | Separate from attrs | Merged into $attrs |
| Project layout | Root-level pages/, components/ | app/ directory (old layout still detected) |
The biggest unknown is usually the UI library. Vuetify 2 → 3 is a large rewrite of component APIs, and BootstrapVue never shipped Vue 3 support, so it has to be replaced. Check every Nuxt module too: some have Nuxt 4 versions, and some have been replaced by built-in features.
How we run a migration
- Audit. List every dependency, module and removed API in use. Mark each as "upgrade", "replace" or "rewrite". This turns a vague project into a clear plan.
- Prepare on the old stack. Upgrade to the final Vue 2 and Nuxt 2 releases. The last Vue 2 release already supports the Composition API and
<script setup>, so new and touched components can be written the Vue 3 way before the switch. - Replace the dead dependencies. Swap Vuex for Pinia, axios for
$fetch, and remove filters and the event bus. Each change can ship on its own. - Switch the framework. Move to Nuxt 4 (or Vue 3 + Vite) on a branch. Vue's migration build (
@vue/compat) can run Vue 2-style code in Vue 3 and log warnings, so the app works while you fix it piece by piece. - Check SEO and performance before launch. Compare rendered HTML, titles, canonicals and status codes page by page against the old site, and measure Core Web Vitals on both. A migration should not cost rankings.
- Release behind a safety net. Ship to staging, run the critical user flows, then cut over with the old build ready to roll back.
What decides the effort
Every migration is different, so a figure from a generic table tells you little. Effort depends on four things more than on app size: the UI library, the number of Nuxt modules, how much logic lives in Vuex and asyncData, and whether there are tests. A brochure site and a large Vuetify dashboard are very different projects, even with the same page count.
That is why we start every migration with an audit of your codebase, not a guess from a form. You get a clear list of what upgrades cleanly, what needs replacing and what needs rewriting, plus a plan to ship it without freezing feature work.
Waiting does not make it cheaper. The longer an app stays on Vue 2 or Nuxt 2, the more each new feature and dependency update costs. Teams that plan the move now choose their timing. Teams that wait often get forced into it by a security audit, a broken dependency or a customer asking awkward questions.
Talk to us before you start
We have built with Vue since the Vue 2 days and ship Nuxt in production for clients today, so we know where these migrations hide their surprises. Book a free call and walk us through your app. You will leave with an honest view of what your upgrade involves, what to do first, and whether you need outside help at all.