# Upgrade de Vue 2 a Vue 3

1. Hacer tests de sistema para los flujos más importantes que tengan componentes de Vue.
2. Instalar la versión de compatibilidad de vue 3, siguiendo las instrucciones en <https://v3-migration.vuejs.org/migration-build.html> hasta el punto 3 (usar las instrucciones de webpack). Ignorar warnings de peer dependencies.

```
// config/webpack/environment.js
// ...
environment.config.merge({
  resolve: {
    alias: {
      'vue': '@vue/compat/dist/vue.esm-browser.js',
    },
  },
});
```

```
// config/webpack/loaders/vue.js

module.exports = {
  test: /\\.vue$/,
  loader: 'vue-loader',
  options: {
    compilerOptions: {
      compatConfig: {
        MODE: 2,
      },
    },
  },
};
```

1. Ejecutar `./bin/webpack-dev-server` en la carpeta del proyecto e ir resolviendo uno a uno los warnings y errores hasta que compile y los tests pasen.
2. Buscar alternativas a librerías usadas o actualizarlas.
   * vee-validate 3 -> vee-validate 4 (no tiene guía de migración, el autor recomienda tratar vee-validate 4 como una librería nueva)
   * vue-js-modal -> modal de [HeadlessUI](https://headlessui.com/)
   * v-tooltip -> [floating-vue](https://github.com/Akryum/floating-vue)
   * [vuex 3 -> vuex 4](https://vuex.vuejs.org/guide/migrating-to-4-0-from-3-x.html) (en un proyecto de cero recomendaría Pinia pero en un upgrade no vale la pena cambiar)
   * [vue-router 3 -> vue-router 4](https://router.vuejs.org/guide/migration/)
3. `npm ls vue` en la raiz del proyecto debería retornar *solo* vue 3.

```bash
❌
❯ npm ls vue
app@0.1.0 /project
├── vue@3.2.37
└─┬ vue-linkify@1.0.1
  └── vue@2.7.8

✅
❯ npm ls vue
app@0.1.0 /project
└── vue@3.2.37
```

1. Una vez que la app funcione, no necesariamente al 100% pero por lo menos que el trabajo de migración esté semicompleto, romper todo de nuevo instalando la receta de frontend de potassium. Acá hay tres alternativas:
   * Crear un proyecto nuevo con potassium en otra carpeta y comparar los cambios con lo que tienen, usando algo como [Beyond Compare](https://www.scootersoftware.com/) o [Meld](https://meldmerge.org/), para ir actualizando a mano.
   * Instalar la receta de frontend encima del proyecto, forzando la sobreescritura y revisar qué archivos sobran. Tiene la desventaja que hay que estar revisando el diff de git para ver qué cosas del proyecto cambiaron.
   * Instalar shakapacker a mano, siguiendo la [guía de migración](https://github.com/shakacode/shakapacker/blob/master/docs/v6_upgrade.md) y después revisar los cambios que hace la receta de frontend para que quede igual que el resto de los proyectos.
2. **No es necesario reescribir los componentes ya existentes a typescript**, se pueden ir migrando de a poco.
3. **No es necesario reescribir los componentes ya existentes a la Composition API + \*\*\*\*`script setup`**, se pueden ir migrando de a poco.
4. Al final de esto el proyecto debería quedar con Vue 3 (sin el build de compatibilidad a menos que no hayan encontrado alternativa a las librerías usadas), Tailwind 3 y Shakapacker.

### Comentarios Kalio

1. Los filtros ya no existen en vue3 (con la compatibility build tampoco funcionaban, al menos que haya hecho algo mal XD). lo que hice fue:
   * definir los filtros como funciones globales:

     ```javascript
     app.config.globalProperties.$filters = {
         camelizeKeys,
         camelize,
         deaccentisize,
         capitalize,
       };
     ```
   * luego se pueden usar asi: `:startup="$filters.camelizeKeys(<%= @startup.to_json %>)"`
   * en caso de que el proyecto use filtros nesteados, por ej. `filtro1 | filtro2 | filtro3`, se puede definir una función que los aplique en orden:

     ```javascript
     export function filterChain(value, filters) {
       if (!value) return null;

       let result = value;
       filters.forEach((filter) => {
         result = filter(result);
       });

       return result;
     }
     ```

     y luego se puede usar asi:

     ```javascript
     $filters.filterChain(state, [$filters.capitalize, $filters.split])
     ```
2. En vue3 `v-bind="$attrs"` reemplaza a `v-on="$listeners`. Si se quiere agregar algun input custom o modificar alguno, se puede hacer asi:

   ```javascript
   attrs() {
       return {
         ...this.$attrs,
         onInput: (event) => this.$emit('update:modelValue', event.target.value),
       };
     },
   ```

   notar que los eventos vienen prefixeados con `on`
3. `beforeDestroy` esta deprecated, no se si con la compatibility build sigue funcionando, en vue3 hay que remplazarlo por `beforeUnmount`
4. Si se usaba un EventBus con `Vue`, se puede reemplazar por algo como <https://github.com/developit/mitt>, o <https://vueuse.org/core/useEventBus/>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://la-guia.platan.us/upgrades/upgrade_de_vue_2_a_vue_3.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
