Blog
Apr 25, 2025 - 6 MIN READ
From Nuxt 2 to Vue 3: My Journey of Migration and Growth

From Nuxt 2 to Vue 3: My Journey of Migration and Growth

A detailed account of my experience upgrading a project from Nuxt 2 to Vue 3, replacing Vuex with Pinia, and the valuable lessons learned along the way.

Mohamed Eslam

Mohamed Eslam

Recently, I've been working on upgrading a project from Nuxt 2 to Vue 3 only, and replacing Vuex with Pinia. The experience was full of challenges, but I learned so much from it!

Why I Decided to Upgrade and Leave Nuxt Behind

✅ Better Performance and Composition API Support

Vue 3 offers superior performance and much better support for the Composition API, making the development experience significantly smoother.

✅ Pinia vs Vuex

Pinia is much simpler than Vuex and doesn't require mutations like Vuex does, making state management much more straightforward and intuitive.

✅ Nuxt 2 Limitations

Nuxt 2 relies on Vue 2, and its support is declining. I needed to take a step forward and transition directly to Vue 3 without depending on Nuxt.

✅ Project Requirements

The project requirements specifically needed Vue 3 only to work with Laravel Mix, which was a key factor in my decision.

The Biggest Challenges I Faced

🔹 Losing Nuxt Features

In Nuxt, I had ready-made features like auto-imports, file-based routing, and SSR. With Vue 3, I had to configure everything manually, which was quite a learning curve.

🔹 Vue Router Changes

Instead of NuxtLink, I now had to use createRouter with createWebHistory(). This was a significant change in how I defined routes and handled navigation.

🔹 Converting Components from Options API to Composition API

The setup() function completely changed my way of thinking about component structure. But honestly, it makes the code cleaner and much easier to read.

🔹 Migrating from Vuex to Pinia

Vuex relied on mutations and actions, but Pinia makes state management more direct and easier to work with. The transition was smoother than expected.

What I Gained from This Experience

💡 Deeper Understanding of Vue Core Concepts

Leaving Nuxt 2 behind helped me understand Vue's core concepts much more deeply. I now have a better grasp of what's happening under the hood.

💡 Gradual Migration is Key

There's no need to rush the upgrade process. Try everything step by step to ensure your app works without issues. This approach saved me from many potential problems.

💡 Documentation is Your Best Friend

Reading the documentation before starting the migration helped me tremendously. It's essential to understand the changes before diving in.

The Migration Process

Step 1: Planning and Preparation

I started by thoroughly reading the Vue 3 migration guide and understanding the breaking changes. This preparation phase was crucial for a smooth transition.

Step 2: Setting Up Vue 3

# Installing Vue 3 and related packages
npm install vue@3 vue-router@4 pinia@2
npm install -D @vitejs/plugin-vue

Step 3: Router Configuration

// Before (Nuxt 2)
// Nuxt handled routing automatically

// After (Vue 3)
import { createRouter, createWebHistory } from 'vue-router'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: () => import('@/views/Home.vue')
  },
  // ... more routes
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

Step 4: State Management with Pinia

// Before (Vuex)
export default {
  state: {
    user: null
  },
  mutations: {
    SET_USER(state, user) {
      state.user = user
    }
  },
  actions: {
    async fetchUser({ commit }) {
      const user = await api.getUser()
      commit('SET_USER', user)
    }
  }
}

// After (Pinia)
export const useUserStore = defineStore('user', () => {
  const user = ref(null)
  
  const fetchUser = async () => {
    user.value = await api.getUser()
  }
  
  return { user, fetchUser }
})

Step 5: Component Migration

<!-- Before (Options API) -->
<template>
  <div>{{ message }}</div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello Vue 2!'
    }
  },
  methods: {
    updateMessage() {
      this.message = 'Updated!'
    }
  }
}
</script>

<!-- After (Composition API) -->
<template>
  <div>{{ message }}</div>
</template>

<script setup>
import { ref } from 'vue'

const message = ref('Hello Vue 3!')

const updateMessage = () => {
  message.value = 'Updated!'
}
</script>

Key Benefits of the Migration

🚀 Performance Improvements

  • Smaller Bundle Size: Vue 3's tree-shaking is more effective
  • Faster Rendering: Improved virtual DOM implementation
  • Better Memory Management: Reduced memory leaks and better garbage collection

🛠️ Developer Experience

  • TypeScript Support: Better TypeScript integration out of the box
  • Composition API: More flexible and reusable logic
  • Better Tooling: Enhanced DevTools and debugging capabilities

📱 Modern Features

  • Teleport: Better modal and popup handling
  • Fragments: Multiple root nodes in components
  • Suspense: Better async component handling

Lessons Learned

  1. Plan Thoroughly: Don't start migration without a solid plan
  2. Test Incrementally: Migrate one component at a time
  3. Keep Backups: Always have a working version to fall back to
  4. Document Changes: Keep track of what you've changed and why
  5. Team Communication: Ensure everyone understands the migration process

Current Status

Now the project is running smoothly with Vue 3 and Pinia! 😍

The migration was challenging but incredibly rewarding. I now have a much deeper understanding of Vue's ecosystem and feel more confident working with modern Vue applications.

Looking Forward

This experience has opened up new possibilities for future projects. I'm now considering:

  • Exploring Nuxt 3 for new projects (best of both worlds!)
  • Implementing more advanced Vue 3 features
  • Sharing knowledge with other developers going through similar migrations

Questions for You

Have you tried doing an upgrade before? Or have you considered leaving Nuxt to work with Vue only? I'd love to hear about your experiences and maybe share some tips!

What migration challenges have you faced, and how did you overcome them? Let's discuss in the comments! 💪🔥


This post was originally shared on LinkedIn. Follow me for more insights on Vue development and migration strategies!

Copyright © 2026 Mohamed Eslam. All rights reserved.