Compartir en Twitter
Go to Homepage

GUÍA COMPLETA PARA MIGRAR DE VUE 2 A VUE 3 CON EJEMPLO PRÁCTICO

December 4, 2025

Introducción a la migración de Vue 2 a Vue 3

Vue.js es un framework progresivo de JavaScript ampliamente utilizado para construir interfaces de usuario dinámicas y reactivas. Desde su lanzamiento en 2014, ha ganado popularidad gracias a su simplicidad, flexibilidad y curva de aprendizaje suave. En septiembre de 2020, se lanzó Vue 3, introduciendo mejoras significativas en rendimiento, sintaxis y herramientas para desarrolladores. Sin embargo, migrar un proyecto existente de Vue 2 a Vue 3 puede parecer un desafío debido a los cambios de ruptura en Vue 3. Este tutorial proporciona una guía paso a paso para realizar esta migración, utilizando un proyecto de ejemplo para ilustrar los conceptos clave y las mejores prácticas. Al final, tendrás una comprensión clara de cómo actualizar tu aplicación y aprovechar las nuevas funcionalidades de Vue 3.

Vue 3 ofrece optimizaciones como un sistema de reactividad más eficiente, mejor soporte para TypeScript y la introducción de la Composition API, que permite una organización más modular del código. Aunque Vue 2 sigue siendo funcional, su soporte oficial finalizó a finales de 2023, lo que hace que la migración sea una prioridad para muchos desarrolladores que desean mantener sus proyectos actualizados y compatibles con las últimas tendencias tecnológicas.

Preparativos para la migración

Antes de comenzar la migración, es fundamental preparar el entorno y el proyecto. Esto incluye revisar las dependencias, hacer copias de seguridad y entender los cambios que introduce Vue 3. A continuación, se detallan los pasos iniciales para garantizar una transición fluida.

Primero, asegúrate de que tu proyecto de Vue 2 esté en un estado estable. Corrige cualquier error pendiente y asegúrate de que todas las funcionalidades estén operativas. Realiza una copia de seguridad completa del proyecto, preferiblemente utilizando un sistema de control de versiones como Git. Por ejemplo, puedes crear una nueva rama para la migración:

git checkout -b vue3-migration

A continuación, revisa las dependencias en el archivo package.json. Algunas bibliotecas utilizadas en Vue 2 podrían no ser compatibles con Vue 3, como versiones antiguas de Vuex o Vuetify. Usa el comando npm outdated para identificar dependencias desactualizadas:

npm outdated

Finalmente, familiarízate con la guía de migración oficial de Vue. Esta documentación detalla los cambios de ruptura, como la eliminación de filtros y modificaciones en la API de eventos. Aunque este tutorial cubrirá los principales cambios, la guía oficial es un recurso esencial para casos específicos.

Configuración del entorno para Vue 3

El entorno de desarrollo debe actualizarse para soportar Vue 3. Esto implica instalar herramientas compatibles, como Vue CLI o Vite, y actualizar el núcleo de Vue. A continuación, se explica cómo configurar un proyecto para la migración.

Si tu proyecto utiliza Vue CLI, asegúrate de tener instalada la versión más reciente. Ejecuta el siguiente comando para actualizar globalmente Vue CLI:

npm install -g @vue/cli@latest

Alternativamente, puedes optar por Vite, una herramienta de construcción más moderna y rápida que es altamente recomendada para proyectos de Vue 3. Para crear un nuevo proyecto con Vite, usa:

npm create vite@latest vue3-project --template vue
cd vue3-project
npm install
npm run dev

Una vez configurado el entorno, actualiza la dependencia principal de Vue en package.json. Reemplaza la versión de Vue 2 con la más reciente de Vue 3:

"dependencies": {
  "vue": "^3.4.0"
}

Ejecuta npm install para instalar la nueva versión. Si tu proyecto utiliza Vue CLI, también necesitarás actualizar el plugin de Vue CLI para soportar Vue 3:

vue add vue-next

Este comando instala la migration build de Vue 3, una versión especial que permite ejecutar aplicaciones de Vue 2 en un modo de compatibilidad mientras realizas los cambios necesarios.

Actualización de la estructura del proyecto

La estructura de un proyecto de Vue 3 difiere ligeramente de la de Vue 2, especialmente en la configuración de archivos y la forma en que se inicializa la aplicación. A continuación, se detalla cómo adaptar la estructura existente.

En Vue 2, el punto de entrada principal suele ser main.js, donde se crea una instancia de Vue con el método new Vue(). En Vue 3, este enfoque cambia con la introducción de la función createApp. Actualiza tu archivo main.js de la siguiente manera:

// Vue 2
import Vue from "vue";
import App from "./App.vue";

new Vue({
    render: (h) => h(App),
}).$mount("#app");

// Vue 3
import { createApp } from "vue";
import App from "./App.vue";

const app = createApp(App);
app.mount("#app");

Este cambio refleja la nueva API global de Vue 3, que es más modular y permite crear múltiples instancias de aplicaciones en la misma página. Además, elimina la necesidad de un constructor global, lo que mejora la organización del código en Vue.

Si tu proyecto utiliza Vue Router, actualízalo a la versión compatible con Vue 3. Actualiza package.json:

"dependencies": {
  "vue-router": "^4.2.0"
}

Luego, ajusta la configuración de Vue Router en tu archivo de enrutamiento:

// Vue 2
import Vue from "vue";
import VueRouter from "vue-router";

Vue.use(VueRouter);

const routes = [{ path: "/", component: Home }];

const router = new VueRouter({
    routes,
});

// Vue 3
import { createRouter, createWebHistory } from "vue-router";

const routes = [{ path: "/", component: Home }];

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

export default router;

En Vue 3, los complementos como Vue Router se registran directamente en la instancia de la aplicación en lugar de usar Vue.use():

import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";

const app = createApp(App);
app.use(router);
app.mount("#app");

Adaptación de componentes y directivas

Los componentes en Vue 3 requieren ajustes debido a los cambios en la sintaxis y las directivas. Uno de los cambios más significativos es la eliminación de los filtros, que eran comunes en Vue 2 para formatear datos en las plantillas. En Vue 3, se recomienda usar métodos o propiedades computadas.

Por ejemplo, un filtro en Vue 2 para capitalizar texto se vería así:

// Vue 2
Vue.filter('capitalize', function (value) {
  if (!value) return ''
  return value.charAt(0).toUpperCase() + value.slice(1)
})

<template>
  <p>{{ text | capitalize }}</p>
</template>

En Vue 3, reemplaza el filtro con una propiedad computada:

// Vue 3
import { computed } from "vue";

export default {
    props: ["text"],
    setup(props) {
        const capitalizedText = computed(() => {
            if (!props.text) return "";
            return props.text.charAt(0).toUpperCase() + props.text.slice(1);
        });

        return { capitalizedText };
    },
};
<template>
    <p>{{ capitalizedText }}</p>
</template>

Otro cambio importante es la directiva v-model. En Vue 2, v-model en componentes personalizados usaba value como prop y emitía el evento input. En Vue 3, puedes personalizar los nombres de los props y eventos, y se introduce el soporte para múltiples v-model. Por ejemplo:

// Vue 2
export default {
  props: ['value'],
  methods: {
    updateValue(newValue) {
      this.$emit('input', newValue)
    }
  }
}

// Vue 3
export default {
  props: ['modelValue'],
  emits: ['update:modelValue'],
  setup(props, { emit }) {
    const updateValue = (newValue) => {
      emit('update:modelValue', newValue)
    }

    return { updateValue }
  }
}
<template>
    <input :value="modelValue" @input="updateValue($event.target.value)" />
</template>

Estos cambios reflejan el enfoque de Vue 3 hacia una mayor flexibilidad y claridad en la gestión de componentes en Vue.

Migración a la Composition API

La Composition API es una de las mayores innovaciones de Vue 3. Aunque no es obligatorio usarla, ofrece una forma más modular de organizar la lógica de los componentes, especialmente en proyectos grandes. A continuación, se muestra cómo migrar un componente de la Options API (usada en Vue 2) a la Composition API.

Considera un componente simple en Vue 2 que muestra un contador:

// Vue 2 (Options API)
export default {
    data() {
        return {
            count: 0,
        };
    },
    methods: {
        increment() {
            this.count++;
        },
    },
};
<template>
    <div>
        <p>Contador: {{ count }}</p>
        <button @click="increment">Incrementar</button>
    </div>
</template>

En Vue 3, usando la Composition API, el mismo componente se reescribe así:

// Vue 3 (Composition API)
import { ref } from "vue";

export default {
    setup() {
        const count = ref(0);

        const increment = () => {
            count.value++;
        };

        return { count, increment };
    },
};
<template>
    <div>
        <p>Contador: {{ count }}</p>
        <button @click="increment">Incrementar</button>
    </div>
</template>

La Composition API utiliza ref para crear variables reactivas y organiza la lógica en la función setup. Esto facilita la reutilización de código y la separación de preocupaciones. Si tu proyecto es pequeño, puedes seguir usando la Options API, ya que Vue 3 la soporta completamente.

Gestión del estado con Pinia

En Vue 2, Vuex era la biblioteca estándar para la gestión del estado. En Vue 3, Pinia se ha convertido en la opción recomendada debido a su simplicidad y mejor integración con la Composition API. Para migrar de Vuex a Pinia, primero instala Pinia:

npm install pinia

Configura Pinia en tu aplicación:

import { createApp } from "vue";
import { createPinia } from "pinia";
import App from "./App.vue";

const app = createApp(App);
const pinia = createPinia();
app.use(pinia);
app.mount("#app");

Crea una tienda con Pinia. Por ejemplo, una tienda para gestionar un contador:

// src/stores/counter.js
import { defineStore } from "pinia";

export const useCounterStore = defineStore("counter", {
    state: () => ({
        count: 0,
    }),
    actions: {
        increment() {
            this.count++;
        },
    },
});

Usa la tienda en un componente:

import { useCounterStore } from "@/stores/counter";

export default {
    setup() {
        const counterStore = useCounterStore();

        return { counterStore };
    },
};
<template>
    <div>
        <p>Contador: {{ counterStore.count }}</p>
        <button @click="counterStore.increment">Incrementar</button>
    </div>
</template>

Pinia elimina la complejidad de las mutaciones de Vuex y proporciona una API más intuitiva, lo que mejora la gestión del estado en Vue 3.

Ejemplo práctico: Proyecto de lista de tareas

Para ilustrar el proceso de migración, crearemos una aplicación simple de lista de tareas que migra de Vue 2 a Vue 3. Este proyecto utiliza Vue Router para la navegación, Pinia para la gestión del estado y la Composition API para los componentes.

Estructura del proyecto

La estructura inicial del proyecto es la siguiente:

├── src
│   ├── assets
│   ├── components
│   │   ├── TaskList.vue
│   │   ├── TaskForm.vue
│   ├── router
│   │   ├── index.js
│   ├── stores
│   │   ├── tasks.js
│   ├── views
│   │   ├── Home.vue
│   │   ├── About.vue
│   ├── App.vue
│   ├── main.js
├── package.json

Configuración inicial (Vue 2)

En Vue 2, el archivo main.js se vería así:

import Vue from "vue";
import App from "./App.vue";
import VueRouter from "vue-router";
import routes from "./router";

Vue.use(VueRouter);

const router = new VueRouter({
    routes,
});

new Vue({
    router,
    render: (h) => h(App),
}).$mount("#app");

El componente TaskList.vue usa la Options API:

export default {
    data() {
        return {
            tasks: [],
        };
    },
    methods: {
        addTask(task) {
            this.tasks.push(task);
        },
    },
};
<template>
    <div>
        <h2>Lista de tareas</h2>
        <ul>
            <li v-for="task in tasks" :key="task.id">{{ task.name }}</li>
        </ul>
    </div>
</template>

Migración a Vue 3

Actualiza main.js para usar Vue 3 y Pinia:

import { createApp } from "vue";
import { createPinia } from "pinia";
import App from "./App.vue";
import router from "./router";

const app = createApp(App);
app.use(createPinia());
app.use(router);
app.mount("#app");

Convierte TaskList.vue a la Composition API y usa Pinia:

import { useTasksStore } from "@/stores/tasks";
import { ref } from "vue";

export default {
    setup() {
        const tasksStore = useTasksStore();
        const newTask = ref("");

        const addTask = () => {
            if (newTask.value) {
                tasksStore.addTask({ id: Date.now(), name: newTask.value });
                newTask.value = "";
            }
        };

        return { tasksStore, newTask, addTask };
    },
};
<template>
    <div>
        <h2>Lista de tareas</h2>
        <input v-model="newTask" placeholder="Nueva tarea" />
        <button @click="addTask">Añadir</button>
        <ul>
            <li v-for="task in tasksStore.tasks" :key="task.id">
                {{ task.name }}
            </li>
        </ul>
    </div>
</template>

Crea la tienda tasks.js:

import { defineStore } from "pinia";

export const useTasksStore = defineStore("tasks", {
    state: () => ({
        tasks: [],
    }),
    actions: {
        addTask(task) {
            this.tasks.push(task);
        },
    },
});

Pruebas y despliegue

Una vez migrado el proyecto, ejecuta pruebas para verificar que todas las funcionalidades funcionan correctamente. Usa herramientas como Vitest para pruebas unitarias:

npm install vitest --save-dev

Configura un script en package.json:

"scripts": {
  "test": "vitest"
}

Escribe una prueba para el componente TaskList.vue:

import { mount } from "@vue/test-utils";
import TaskList from "@/components/TaskList.vue";
import { createPinia } from "pinia";

describe("TaskList.vue", () => {
    it("adds a task", async () => {
        const pinia = createPinia();
        const wrapper = mount(TaskList, {
            global: {
                plugins: [pinia],
            },
        });

        await wrapper.find("input").setValue("Nueva tarea");
        await wrapper.find("button").trigger("click");

        expect(wrapper.text()).toContain("Nueva tarea");
    });
});

Finalmente, genera el build de producción con:

npm run build

Esto crea una carpeta dist con los archivos optimizados para producción.

Conclusiones

Migrar de Vue 2 a Vue 3 es un proceso que, aunque presenta desafíos debido a los cambios de ruptura, ofrece recompensas significativas en términos de rendimiento, flexibilidad y soporte a largo plazo. Este tutorial ha cubierto los pasos esenciales, desde la preparación del entorno hasta la implementación de un proyecto práctico, destacando la importancia de herramientas como Vite, Pinia y la Composition API. Al seguir estas mejores prácticas, los desarrolladores pueden modernizar sus aplicaciones y aprovechar las innovaciones de Vue 3. La clave para una migración exitosa es planificar cuidadosamente, probar exhaustivamente y aprovechar los recursos de la comunidad de Vue para resolver problemas específicos. Con estos pasos, tu proyecto estará listo para enfrentar las demandas del desarrollo web moderno.