Migrando una aplicación de 1000 componentes de clase a Vue 3

Rate this content
Bookmark

Vue 3 es increíble, pero muchos de nosotros todavía estamos atrapados en un monolito de Vue 2. Algunos de nosotros estamos aún más atrapados debido a las elecciones tecnológicas realizadas antes de que Vue 3 estuviera siquiera en el roadmap. Vamos a describir el proceso de migración de un proyecto grande a Vue 3 y Vite. Técnicas que podemos emplear para obtener algunos beneficios antes, procesos que podemos aplicar para hacer las cosas más rápidamente. Cosas que podemos hacer para lograrlo eventualmente.

28 min
15 May, 2023

Video Summary and Transcription

La charla trata sobre la migración de una aplicación de vista frontend grande de Vue 2 a Vue 3. La estrategia implica convertir componentes al API de Composición, cambiar de Vuex a Pinea y superar los desafíos con la configuración de Vite. El proceso de migración incluye seleccionar componentes basados en el roadmap del producto, mejorar la seguridad de tipos y reducir el boilerplate. Los resultados de la migración incluyen una mejor verificación de tipos, pruebas más rápidas y un código más seguro.

Available in English

1. Introducción a Bagel Solutions y migración a V7

Short description:

Hola a todos. Mi nombre es Nikola y soy el dueño de una empresa llamada Bagel Solutions. He estado trabajando con V7 en su plataforma de aprendizaje automático, que se ha convertido en un sistema completo de aprendizaje automático de IA. Actualmente, me estoy enfocando en el desarrollo frontend y estoy involucrado en la migración de una gran aplicación de vista frontend de Vue 2 a Vue 3. Esta charla comparte nuestra experiencia, conocimiento y estrategia en este proceso. V7 es un monolito frontend masivo con 360,000 líneas de código, lo que presenta desafíos únicos. Incluye características típicas de una aplicación de una sola página, así como partes caprichosas y similares a Photoshop. Tenemos alrededor de mil componentes, pero una parte significativa será eliminada debido a una reescritura importante del subsistema.

Mi nombre es Nikola y soy el dueño de una empresa llamada Bagel Solutions, porque Bagel es mi apodo. Durante los últimos cuatro años, he estado trabajando con V7 en su plataforma de aprendizaje automático. Comenzó como visión por computadora, pero se ha convertido en mucho más. Ahora es algo así como un sistema completo de aprendizaje automático de IA.

Comencé como desarrollador backend, pero actualmente, desde hace aproximadamente un año, me he enfocado en el frontend. Durante los últimos meses, hemos estado involucrados en la migración de su enorme aplicación de vista frontend de Vue 2 a Vue 3. Aún no hemos terminado, pero esta charla trata sobre ese proceso. Entonces, lo que no es esta charla, es una historia de éxito. Nuevamente, aún no hemos terminado. Todavía estamos en proceso. No es una alarde de lo rápido que lo hicimos de ninguna manera, porque nuevamente, aún no hemos terminado. Tampoco es realmente un tutorial, porque estamos haciendo algunas cosas específicas para nuestro proyecto que funcionan para nosotros. Puede que no funcione para usted. Puede que funcione, pero no hay garantía. Lo que es, es una compartición de la experiencia que tenemos con esto, el conocimiento que hemos adquirido, y la estrategia que hemos utilizado. Y nuevamente, probablemente no sea completamente aplicable a su caso. Pero espero que al menos sea interesante.

Entonces, ¿qué es v7? Básicamente, es un monolito frontend enorme. 360,000 líneas de código, más o menos. Y esto solo cuenta el TypeScript, sin contar nada más. Hay partes que se parecen a una aplicación de una sola página típica, gestión de datos, gestión de cuentas. Pero tienen problemas con los que necesitan lidiar, que una aplicación de una sola página típica no tiene, como renderizar listas de tarjetas con cientos de miles de elementos, o cosas así. Hay partes que parecen caprichosas. Este es nuestro editor de flujo de trabajo, donde básicamente arrastras diferentes elementos del DOM sobre un lienzo, los conectas con flechas, cosas así. Y también hay partes que funcionan y se ven como Photoshop. Este es nuestro UI de anotaciones, donde usas diferentes herramientas para dibujar diferentes tipos de anotaciones sobre un lienzo, que renderiza una imagen o un video u otra cosa visual. Tenemos alrededor de mil componentes en el proyecto. Pero para ser justos, estamos en medio o cerca del final de una reescritura importante de un subsistema bastante grande. Estimo que aproximadamente el 20% de esos componentes probablemente serán eliminados.

2. Estrategia de migración y objetivos

Short description:

Inicialmente decidimos utilizar componentes de clase de Vue debido a la falta de ingenieros frontend y nuestra familiaridad con las clases. Sin embargo, migrar a Vue 3 presenta desafíos porque los componentes de clase no se ejecutan en Vite o Vue 3. A pesar del posible soporte para componentes de clase en el futuro, estamos cambiando a la API de Composición como nuevo estándar. Nuestros objetivos de migración incluyen cambiar todos los componentes a la API de Composición, cambiar de UX a Binia, ejecutar tanto nuestra aplicación como el storybook en Vite, y cambiar Jest a Vitest. Para evitar interrupciones y errores, adoptamos una estrategia en la que un ingeniero convierte dos componentes en un sprint, con cada conversión limitada a dos horas. Además, cualquier código nuevo agregado debe utilizar la API de Composición.

Ahora, nos reservamos el derecho de mantener algunos de ellos por razones específicas, pero hablaré de eso más adelante. Tecnológicamente hablando, estamos utilizando TypeScript en su totalidad. Estamos utilizando VUEX, y se ha vuelto bastante cargado con el tiempo. Tenemos una docena aproximadamente de módulos. Ya no se sienten muy bien diseñados, porque hemos sido una startup durante un buen período, por lo que hemos estado agregando iterativamente sin una dirección asombrosa. Ya sabes, las startups cometen errores.

Porque estamos utilizando... Bueno, primero, decidimos utilizar componentes de clase de Vue. Esto fue muy temprano en el ciclo de desarrollo del producto, hace unos tres años y medio más o menos, y decidimos seguir con eso porque, en primer lugar, no teníamos muchos ingenieros frontend. Muchos de nosotros éramos full-stack y las clases eran algo con lo que estábamos más familiarizados. Parecía ser la forma de hacerlo en ese momento, y en ese momento también parecía ser un enfoque que tenía un mejor soporte de TypeScript debido a los decoradores de clase y los decoradores de clase de VueX, que también usamos como biblioteca. Pero sí, esa fue una decisión tomada en ese momento.

Para las pruebas, por supuesto, usamos Jest con Vue Test Utils, y tenemos una configuración de storybook, que utilizamos como catálogo de componentes, pero no dentro del contexto de escribir pruebas ni nada por el estilo. Por lo tanto, claramente, para migrar a Vue 3, el problema número uno es el hecho de que utilizamos componentes de clase. Eso significa que hay más trabajo para migrar un componente que con la API de opciones, y eso significa que desde el principio no podemos comenzar con la configuración de Vite para la compilación frontend en Vite porque los componentes de clase no se ejecutan realmente en Vite o en Vue 3. Ahora, en este momento, según tengo entendido, hay algunas PR en revisión para los componentes de clase de Vue y las bibliotecas de clase de VueX, potencialmente incluso un candidato a versión o algo así, donde se agregará este soporte. Por lo tanto, es posible que para cuando terminemos la migración, también sea posible ejecutar componentes de clase en Vite, pero aún así estamos cambiando a la API de Composición simplemente porque es un nuevo estándar y preferimos utilizar el estándar en lugar de una alternativa de terceros. Bueno, eso es lo que hacemos ahora.

Nuestra lista de objetivos para considerar que esta migración está completa es cambiar todos los componentes a la API de Composición, al menos aquellos que vamos a mantener, y tal vez algunos más, y nuevamente, hablaré de eso un poco más adelante, cambiar de UX a Binia, porque es el nuevo estándar, hacer que nuestra aplicación y el storybook se ejecuten en Vite, y hacer que Jest cambie a Vitest, lo que significa que también utiliza la misma configuración de Vite, lo cual es una gran ventaja con Vitest o Jest.

Entonces, necesitamos una estrategia para esto, y desde el principio decidimos que un gran esfuerzo único no es una buena idea. No podemos hacer un gran esfuerzo de simplemente migrar, migrar, migrar hasta que terminemos, y luego pasar a otra cosa. En primer lugar, nuestro equipo es bastante grande ahora, tenemos alrededor de 30 ingenieros, e incluso con ese tamaño, probablemente llevará semanas migrar todos esos componentes, especialmente porque nos pisaremos los unos a los otros. Estamos garantizados de crear errores de esta manera, hay demasiado código que se está cambiando como para que eso no suceda. Y habrá demasiados retrasos en nuestro trabajo de producto, así que sí, no estamos de acuerdo con eso. Para mejorar nuestro proceso, decidimos que debe ser algo que nos brinde beneficios a medida que avanzamos, y no cuando terminemos, y debe ser lo menos disruptivo posible.

Entonces, el enfoque básico que adoptamos es que un ingeniero convierte dos componentes en un sprint, y nuestro sprint dura dos semanas, para nosotros, y esta conversión de un solo componente tiene un límite de tiempo de dos horas. Eso significa que si parece que llevará más de dos horas, ese ticket se pone inmediatamente en espera y tomamos el siguiente. El razonamiento es que a medida que adquirimos experiencia haciendo estas conversiones, podemos aumentar la velocidad, tal vez cambiar las reglas para elegir más componentes, y luego podemos volver a visitar esos tickets que pusimos en espera, para ver si tal vez será más rápido esta vez porque sabemos más. Y luego, como parte de todo este esfuerzo, hay una regla adicional de que cualquier código nuevo que escribamos, cualquier componente nuevo que agreguemos a la base de código, debe utilizar la API de Composición. Por lo tanto, no más introducción de componentes de clase adicionales a la base de código.

3. Selección y Ejecución de Componentes

Short description:

La estrategia para seleccionar componentes implica alinearse con la hoja de ruta del producto, migrar componentes antes de que comience el desarrollo e identificar áreas en el código para una migración paralela. El enfoque se centra en construir conocimiento, mejorar la seguridad de tipos, reducir el código repetitivo y acelerar el trabajo de funciones. La ejecución implica retrasar la migración de algunos componentes, marcar secciones de la aplicación como migradas y convertir componentes basados en un mapa de componentes de clase a la API de Composición. El objetivo es recopilar conocimiento y mejorar como equipo.

La siguiente parte de la estrategia es cómo seleccionamos estos componentes, y aquí, una vez más, fue importante para nosotros no ser demasiado disruptivos. Por lo tanto, la primera prioridad es alinearse con el producto. Eso significa que entendemos cuál es la hoja de ruta del producto, cuáles son las próximas características que se desarrollarán y qué componentes en el código serán afectados por ese desarrollo. Entonces nos enfocamos en migrar esos componentes primero antes de que comience ese desarrollo, para que el trabajo de funciones se realice en código moderno y no se vea ralentizado por ninguna conversión.

Además de eso, identificamos áreas en nuestro código que podemos migrar juntas, para que partes de la aplicación se modernicen lo antes posible. Y con islas nos referimos a componentes que están relacionados con la construcción de una parte específica del producto, una página específica, tal vez alguna subcaracterística. Y también componentes que interactúan con los mismos Vuex modules, porque presumiblemente eso también se alinea, y nos permite cambiar de Vuex a Pina más fácilmente en paralelo.

El mantra aquí es que, a medida que hacemos esto, necesitamos construir conocimiento. Aprendemos sobre todas las advertencias que podemos, documentamos todo esto y lo compartimos con el resto del equipo para que todos sean más rápidos, y a medida que avanzamos, volvemos a aumentar la velocidad. Esa es nuestra prioridad número uno. Entonces, los efectos que esperamos y que estamos viendo con esta estrategia es que a medida que avanzamos, obtenemos una mejor seguridad de tipos, porque en primer lugar, la API de Composición por defecto tiene una inferencia de tipos más directa y ligeramente mejor. Pina es mucho mejor en inferencia de tipos y verificación de tipos que Vuex. Hay menos código repetitivo, reducimos la cantidad de errores en algunas categorías relacionadas con todo esto. Aceleramos el trabajo de funciones, en realidad, porque las nuevas funciones se construyen sobre un código moderno y obtenemos conocimiento sobre otras cosas que podemos hacer a medida que migrarnos. No solo conversiones, sino también otras cosas en nuestro código, porque efectivamente mientras hacemos esto, estamos auditando nuestro código y encontrando cosas que hicimos mal al principio, o encontrando cosas que podríamos hacer mejor ahora que sabemos más, cosas como esas. Encontrar código no utilizado, agregar documentación que nos falta, encontrar cosas que podríamos reescribir de una mejor manera, agregar pruebas que nos faltan. Fuimos una startup durante gran parte de la vida de este producto, por lo que ahora que somos más grandes y tenemos el tiempo y la capacidad para hacer las cosas correctamente, queremos hacerlo a medida que avanzamos.

Entonces, ¿cómo ejecutamos esto? En primer lugar, hay algunas partes fáciles que podemos hacer. Retrasamos la migración del 20% de los componentes que eventualmente queremos eliminar, pero esto no es una regla estricta. Tenemos esas áreas para convertir que queremos cambiar, por lo que si hay un componente allí que nos permita marcar una gran sección de la aplicación como migrada, entonces podemos dedicar una hora o dos para migrar ese componente. Siempre son una opción. Y luego, la otra parte es que si miramos nuestro código, tenemos alrededor de 100 componentes que se ven como este ejemplo que estoy mostrando. Básicamente, el componente no tiene lógica, es solo una plantilla, solo CSS, y todo lo que hace es exportar una clase vacía, efectivamente. Reemplazamos eso con una exportación predeterminada que simplemente exporta un objeto con un nombre, y técnicamente podríamos reemplazar esto con solo un bloque de script en blanco, o incluso omitir completamente el bloque de script, pero debido a un problema específico, tenemos que exportar este nombre, y lo explicaré en unos pocos diapositivas. Entonces, la siguiente parte de la ejecución son las conversiones reales de componentes, y aquí, realmente, es solo un mapa de lo que es una cosa en componentes de clase y lo que se convierte en una API de Composición. Entonces, realmente no hay mucho de qué hablar aquí. Hay un poco más de complejidad cuando agregamos decoradores de VuexClass, pero aún así, solo estamos mapeando cosas a computadoras, funciones o refs, básicamente, u objetos reactivos. Entonces sí, nada de eso es demasiado difícil. Esto no es un trabajo altamente especializado ni nada por el estilo. Es solo trabajo de rutina, y la parte importante que debemos extraer de esto, y que estamos tratando de extraer de esto, es esa recopilación de conocimiento y difundir ese conocimiento en todo el equipo de ingeniería, y simplemente ayudarnos mutuamente a mejorar en esto.

4. Migración de Vuex a Pinea

Short description:

Una gran parte de la ejecución implica pasar de Vuex a Pinea. Definimos una tienda de Pinea que es un proxy para Vuex. Cambiamos gradualmente del uso directo de Vuex a la tienda de Pinea, componente por componente. La tienda de Pinea comienza completamente tipada, proporciona una mejor documentación y permite la fragmentación en tiendas más pequeñas.

Una gran parte de la ejecución implica pasar de Vuex a Pinea, y esto es algo que especialmente me gusta. Este enfoque que hemos desarrollado es una forma de tener una tienda de Pinea que es un proxy para Vuex. Lo que hacemos aquí es definir una tienda, como lo harías con cualquier otra tienda de Pinea, pero en lugar de usar refs, reactive, getters y acciones para definir el estado interno de la tienda, en su lugar definimos computed que actúan como proxy para el estado o los getters de Vuex, y definimos acciones que actúan como proxy para store.dispatch o store.commit, y luego esos se devuelven mediante el componible de la tienda de Pinea.

Desde el exterior, el efecto de esto es que desde el exterior, la tienda de Pinea se ve como cualquier otra tienda de Pinea, pero internamente, está utilizando Vuex. Esto nos permite cambiar gradualmente del uso directo de Vuex para estas cosas al uso de esa tienda de Pinea, componente por componente, paso a paso, en solicitudes de extracción separadas, conjuntos de cambios separados, y así sucesivamente. Y una vez que encontramos que la parte de Vuex ya no tiene uso directo y todo se hace a través de la tienda de Pinea, podemos eliminar la parte de Vuex y pasar completamente a Pinea al declarar realmente esos refs, esos objetos reactivos y esas acciones dentro de la tienda de Pinea. Y esto es, nuevamente, un solo paso, cambiando solo un archivo y luego eliminando algo de código de otros archivos, y eso es todo.

Como beneficio de esto, hay algunos beneficios adicionales. Uno de ellos es que la tienda de Pinea comienza completamente tipada, por lo que la interfaz está completamente tipada, a diferencia de Vuex que se basa en dispatch y commit, y la única forma de tiparlo realmente es volver a declarar los tipos localmente. Obtenemos una mejor documentación porque ahora la estamos escribiendo nosotros, y esos antiguos módulos probablemente no estén tan bien documentados, y todo está en un solo lugar. Y también podemos fragmentar en tiendas de Pinea más pequeñas, no hay una regla que diga que debe haber una tienda de Pinea por cada módulo de Vuex. Podemos dividir ese módulo en múltiples tiendas o podemos seleccionar diferentes cosas de diferentes módulos de Vuex en una sola tienda de Pinea, si tiene sentido. Y todo esto tiene un riesgo extremadamente bajo.

5. Configuración de Vite y Desafíos de Migración

Short description:

Encontramos algunos desafíos al ejecutar la migración, como problemas de compatibilidad entre Webpack y Vite, el uso de módulos CommonJS y cargadores personalizados en nuestra configuración de Vue-CLI. Sin embargo, pudimos superar estos desafíos utilizando complementos definidos, reemplazando módulos CommonJS y reescribiendo los cargadores personalizados en la sintaxis de beat. Actualmente, estamos utilizando beat como una configuración paralela para el desarrollo local, pero no para las compilaciones de implementación. Además, enfrentamos problemas con Vue testutils v1 y los componentes de script setup, los cuales resolvimos agregando un segundo bloque de script sin el atributo de setup.

Y luego, otra parte de la ejecución es Vite. Así que mucho antes, antes de comenzar esta migración, intentamos configurar una configuración de Vite para ejecutar nuestra aplicación en Vite en lugar de la configuración de Webpack que proporciona Vue CLI. No pudimos hacerlo debido a los componentes de clase, y esto podría ser posible en unas pocas semanas o algo así. Incluso podría ser posible ya, no lo he verificado recientemente. Pero en ese momento no lo era. Así que decidimos ir primero con la migración.

Ahora que tenemos algunas de esas islas migradas de la API de Composición, podemos configurar una configuración de Vite que se ejecutará. Y cuando estamos desarrollando en esas islas, es decir, desarrollando nuevas características, podemos usar esa configuración de Vite en el desarrollo local. Esto hace que sea más rápido, con mejor rendimiento y más agradable de usar. Y luego, si tenemos esta configuración, también podemos usarla para cambiar gradualmente a Vitest, podemos usarla para Storybook, podemos usarla para la extensión de vista previa de JS en VS Code, cosas así.

Hay algunos bloqueadores que tuvimos que identificar y solucionar, pero no son muchos y no fue tan difícil. El primero, el más obvio, es que Webpack se basa en process.env para las variables de entorno, mientras que Vite se basa en import.meta.env, y esto se puede hacer compatible fácilmente utilizando un complemento definido en Webpack o en Vite. Básicamente, en Webpack, usamos el complemento definido para mapear process.env a import.meta.env, y luego el código accede a import.meta.env en todas partes, y esto luego funciona tanto en la configuración de Vue-CLI como en la configuración de Vite. Recomiendo este enfoque y no al revés, simplemente porque cuando eliminamos Vue-CLI, solo tenemos que eliminar esa configuración y no tenemos que cambiar nada en el código base.

La otra parte con la que tuvimos un problema es que todavía estábamos usando algunos módulos CommonJS en algunos lugares, muy raramente, principalmente código heredado o código que hemos tomado de otro lugar. Y esto no fue realmente tan difícil de reemplazar, pero hubo algunas peculiaridades al importar imágenes dinámicamente o cosas por el estilo. Aún así, fue relativamente sencillo de manejar. Y también tenemos un par de cargadores personalizados en nuestra configuración de Vue-CLI. Por ejemplo, tenemos una forma especial de incrustar archivos SVG como componentes Vue. Para eso, tendríamos que eliminar el uso de esos cargadores, es decir, no hacer esas cosas, o reescribirlos en beat, dentro de la sintaxis de beat. Y decidimos optar por esta segunda opción porque realmente no fue tan difícil. Nos llevó tal vez dos o tres horas reimplementar nuestros cargadores en beat. De todo eso, puedo decir que estamos usando beat como una configuración paralela para el desarrollo local. Pero aún no lo estamos utilizando para las compilaciones de implementación.

Ahora, por supuesto, encontramos algunos problemas al ejecutar todo esto. El más notable probablemente es que Vue testutils v1, que es compatible con Vue 2.7, tiene algunos problemas con el script setup. Algunos se solucionaron, pero el que aún está activo para nosotros es que si tienes un componente de script setup y escribes una prueba para un componente que es el padre de ese componente, y tienes una captura de pantalla en esa prueba, el componente hijo que es script setup se renderizará como un stop anónimo. Por lo tanto, no tendrá un nombre en la captura de pantalla. Esto se debe a que, aparentemente, Vue TestUtils v1 no puede inferir el nombre del nombre de archivo para el componente de script setup. Lidiamos con esto agregando un segundo bloque de script en cada componente de script setup, que es un bloque de script normal sin el atributo de setup.

6. Migración de Componentes y Mejoras en las Pruebas

Short description:

Y ese solo exporta el nombre del componente. Crea un problema con un complemento que usamos para ordenar las importaciones en nuestros archivos. Estamos esperando una solución para ese complemento. Otro problema está en el antiguo Vue clásico, dependemos de complementos y extendemos la instancia base de Vue con cosas como Store, Router, Route, etc. Para seguir usando estos, necesitamos composables. Comenzamos a usar JustMock para simular directamente el UseStoreComposable. Cambiamos por completo a PascalCase en nuestras plantillas. Cambiamos gradualmente de Wrapper.find a Wrapper.findComponent. Preferimos usar solo mock o inyectar mocks como store o router en la llamada de shallow mount. Estamos encontrando y eliminando bibliotecas de solo vista.

Y ese solo exporta el nombre del componente. Y esta es la razón por la que así migrados esos componentes básicos hace unas pocas diapositivas atrás. Entonces esto hace que las instantáneas funcionen de nuevo. Pero crea un problema con un complemento que usamos, que es un complemento de prettier que usamos para ordenar las importaciones en nuestros archivos. Cuando un archivo Vue tiene dos bloques de script, el complemento no puede ordenar las importaciones correctamente. Eso significa que probablemente un par de docenas de nuestros archivos Vue no tienen sus importaciones ordenadas, y estamos esperando una solución para ese complemento. No es un gran problema. Sería bueno que todo funcione, pero en unas pocas semanas probablemente lo hará y hará un prettier fix all y eso es todo. Hay algunos problemas más que tenemos que resolver. Uno está en el antiguo Vue clásico, dependemos de complementos y extendemos la instancia base de Vue con cosas como Store, Router, Route y algunas otras cosas que usamos, pero estas son las más comunes. Y para eso, para poder seguir usando estas cosas, necesitamos composables, porque en setup realmente no accedemos a esto. Para obtener un composable de algo como esto, podemos confiar en la función GetCurrentInstance que importamos de Vue, y es extremadamente sencillo. Simplemente llamamos a GetCurrentInstance y luego devolvemos el almacén proxy de esa instancia. Ahora, internamente eso significa que un componente debe estar montado para que esto se defina y se devuelva. Eso significa que el mismo caso también debe estar en la prueba. Por ejemplo, si tienes un composable que internamente usa store, o llama UseStore, entonces ese composable no se puede probar directamente. Debe estar montado en un componente para ser probado. Alternativamente, simplemente usamos JustMock para simular directamente el UseStoreComposable, y luego esto no sucede en absoluto. Simplemente devolvemos algo a través de la simulación, y luego podemos probar el otro composable más directamente. Esto es lo que comenzamos a hacer, simplemente porque encontramos que las pruebas son un poco más unificadas, y la configuración es más fácil, y es bastante sencillo. Hay algunas otras cosas que comenzamos a hacer. Como dije, mientras hacíamos esto, buscábamos cosas en el código base que también podríamos hacer. Algunas cosas que hicimos es que cambiamos por completo a PascalCase. Realmente no teníamos una regla sobre si estábamos usando PascalCase o KebapCase en nuestras plantillas. Ahora, estamos usando completamente PascalCase en las plantillas, con una regla. Comenzamos a cambiar gradualmente de Wrapper.find a Wrapper.findComponent, porque hace las pruebas un poco menos frágiles y un poco más estructuradas. Comenzamos a preferir el uso de solo mock, o inyectar mocks como store o router en la llamada de shallow mount. Esto hace que las pruebas, suena contradictorio, pero un poco más agnósticas del framework, porque cambiar a BTest es tan fácil como hacer una búsqueda y reemplazo en este caso. Nuevamente, las pruebas son más unificadas, como pruebas unitarias, menos integración, y tienden a ejecutarse un poco más rápido debido a ello. Otra cosa que estamos haciendo es encontrar y eliminar bibliotecas que son solo para vista.

7. Resultados, Consejos y Recomendaciones

Short description:

Reemplazamos bibliotecas con componibles de vista. La biblioteca Vue.tsc mejoró la comprobación de tipos y aceleró las pruebas. Migramos 400 componentes, eliminamos los módulos Vue.x y mejoramos el tiempo de compilación. La base de código es más segura y no afecta el trabajo del producto. Se recomiendan PINIAproxies y 2REF.

Principalmente, estamos haciendo esto reemplazando esas bibliotecas con algunos componibles proporcionados por la biblioteca view-use, o un conjunto de bibliotecas. Todo ese conjunto de bibliotecas es increíble para nosotros y realmente nos está ayudando mucho con la migración.

También comenzamos a usar la biblioteca Vue.tsc para la comprobación de tipos. Este es el comprobador de tipos que utiliza Volar, la extensión para VSCode, y hace un trabajo mucho mejor al comprobar los archivos de vista que el comprobador de TypeScript normal. Esto nos permite, además, usar el modo aislado de la opción modules, establecerlo en true en Jest, lo que hace que nuestras pruebas sean mucho más rápidas. Esto tiene el costo de una seguridad de tipos ligeramente menor en las pruebas, pero como la comprobación de Vue.tsc se ejecuta en nuestra CI, esto realmente no es un problema para nosotros y en realidad nos hace más seguros en general, con la ventaja de que las pruebas se ejecutan tres o cuatro veces más rápido.

Entonces, ¿cuáles son los resultados de todo esto? Nos quedan alrededor de 400 componentes por migrar. Nuevamente, comenzamos con 1,000 menos el 20% de los componentes de la V1, que todavía están ahí. Por lo tanto, efectivamente estamos en alrededor de 800 a 200 ahora. Hemos eliminado completamente un par de módulos Vue.x. Tenemos varios procesos PNA en marcha, por lo que estamos en camino de eliminar más módulos Vue.x a medida que avanzamos. Nuestras pruebas, debido a algunos de los cambios, se ejecutan cuatro veces más rápido, si no más. El conjunto completo de pruebas se ejecuta en aproximadamente dos minutos y medio localmente en modo de un solo hilo. Nuestro tiempo de compilación es aproximadamente tres veces más rápido porque pudimos eliminar algunas cosas de allí. Hay menos código, porque la API de composición tiene menos código repetitivo y pudimos eliminar parte del código. En general, encontramos menos errores. La base de código en su conjunto es un poco más segura. El trabajo del producto no se ve afectado en absoluto. En promedio, apostaría a que es más rápido. Realmente no hicimos ninguna medición. Es difícil medir algo así. Realmente nunca retrasamos el trabajo del producto por nada, y cualquier nueva función se está trabajando en una base central más moderna. No puedo imaginar que sea más lento. Como mínimo, está al mismo ritmo.

Como una de las últimas diapositivas, lo que hemos aprendido es básicamente una colección de consejos del día sobre cosas. Solo un par de cosas. PINIAproxies, el proceso que he descrito, es realmente excelente para iniciar gradualmente la experiencia de usuario. Realmente lo recomendaría. 2REF es una función impresionante si desea pasar una propiedad o una clave en un objeto reactivo a un componible como algo reactivo. Esto le permite pasar una sola propiedad en lugar de pasar todas las propiedades a un componible porque el componible realmente solo necesita esa única propiedad.

8. Composables, Assertions, and Future Steps

Short description:

No es necesario reutilizar componibles para justificar su creación. Está claro que los comportamientos separados se pueden organizar dentro de un componente utilizando componibles más pequeños. Las aserciones en las pruebas son más útiles que las pruebas de instantáneas, ya que detectan errores. El conjunto de bibliotecas view-use cubre la mayoría de nuestras necesidades. Nuestras estimaciones incluyen completar los componentes a finales del verano, pasar a PiNeo poco después, una migración completa a Vite y Vue 3 en otoño y, finalmente, pasar completamente a Vitest debido al volumen de pruebas.

Realmente no es necesario reutilizar componibles para justificar su creación. Por lo tanto, puedes tener un componente más grande que tenga varios comportamientos diferentes implementados. Algunos podrían argumentar que debería separarse en componentes más pequeños. Pero también se podría argumentar que puedes organizar esas cosas diferentes dentro del componente en diferentes componibles más pequeños. Aunque se utilicen solo una vez, queda claro que son varias cosas separadas. Proporciona un poco de auto-documentación. Y te permite probar esos comportamientos de forma aislada, lo cual siempre es genial.

Lo otro que encontramos, y esto probablemente sea para nosotros, tal vez para algunos de ustedes, pero definitivamente funciona para nosotros. Las aserciones en las pruebas son mucho más útiles que las pruebas de instantáneas. Encontramos muchas pruebas de instantáneas en nuestro código heredado que realmente no hacen absolutamente nada. Entonces, ni siquiera representan lo que esperaríamos que representaran, porque la configuración para la prueba no estaba como debería haber estado. Y esto estaba en el código, pasó la revisión, realmente no le prestamos atención. Entonces, la prueba no estaba haciendo nada por nosotros. En cambio, si reemplazamos esas pruebas de instantáneas con aserciones explícitas en las cosas en las que realmente estamos interesados, funcionan mucho mejor para nosotros y realmente detectan errores.

Y luego el último consejo o lo que aprendimos es, nuevamente, view-use, ese conjunto de bibliotecas es increíble, cubre el 90% de, bueno, no tus, pero probablemente nuestras necesidades, tal vez las tuyas. Entonces, como última diapositiva, nuestras estimaciones, dónde esperamos estar. Esperamos terminar con los componentes a finales del verano. La gente se tomará tiempo libre, todo eso. Probablemente se ralentizará hacia el final. Esperamos terminar con PiNeo poco después porque lo estamos haciendo en paralelo, hasta cierto punto. Nos gustaría hacer una migración completa a Vite. Entonces, todo, la aplicación, storybook a principios del otoño y luego una migración completa a Vue 3 a mediados del otoño porque ahora estamos convirtiendo la API de composición, ¿verdad? Una vez que hayamos terminado con todo eso, todavía habrá algunos pasos involucrados para realmente cambiar a Vue 3. Y luego la última parte que probablemente terminaremos haciendo es pasar completamente a Vitest, simplemente debido al volumen de pruebas que tenemos. Y sí, eso es todo. Gracias. ¿Hay alguna pregunta?

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

JSNation Live 2021JSNation Live 2021
31 min
Vite: Rethinking Frontend Tooling
Top Content
Vite is a new build tool that intends to provide a leaner, faster, and more friction-less workflow for building modern web apps. This talk will dive into the project's background, rationale, technical details and design decisions: what problem does it solve, what makes it fast, and how does it fit into the JS tooling landscape.
Vue.js London Live 2021Vue.js London Live 2021
34 min
Everything Beyond State Management in Stores with Pinia
Top Content
When we think about Vuex, Pinia, or stores in general we often think about state management and the Flux patterns but not only do stores not always follow the Flux pattern, there is so much more about stores that make them worth using! Plugins, Devtools, server-side rendering, TypeScript integrations... Let's dive into everything beyond state management with Pinia with practical examples about plugins and Devtools to get the most out of your stores.
Vue.js London Live 2021Vue.js London Live 2021
20 min
One Year Into Vue 3
Top Content
Vue 3 may still sound new to many users, but it's actually been released for over a year already. How did Vue 3 evolve during this period? Why did it take so long for the ecosystem to catch up? What did we learn from this process? What's coming next? We will discuss these questions in this talk!
Vue.js London Live 2021Vue.js London Live 2021
8 min
Utilising Rust from Vue with WebAssembly
Top Content
Rust is a new language for writing high-performance code, that can be compiled to WebAssembly, and run within the browser. In this talk you will be taken through how you can integrate Rust, within a Vue application, in a way that's painless and easy. With examples on how to interact with Rust from JavaScript, and some of the gotchas to be aware of.

Workshops on related topic

Vue.js London Live 2021Vue.js London Live 2021
169 min
Vue3: Modern Frontend App Development
Top Content
Featured WorkshopFree
The Vue3 has been released in mid-2020. Besides many improvements and optimizations, the main feature of Vue3 brings is the Composition API – a new way to write and reuse reactive code. Let's learn more about how to use Composition API efficiently.

Besides core Vue3 features we'll explain examples of how to use popular libraries with Vue3.

Table of contents:
- Introduction to Vue3
- Composition API
- Core libraries
- Vue3 ecosystem

Prerequisites:
IDE of choice (Inellij or VSC) installed
Nodejs + NPM
Vue.js London Live 2021Vue.js London Live 2021
117 min
Using Nitro – Building an App with the Latest Nuxt Rendering Engine
Top Content
Workshop
We'll build a Nuxt project together from scratch using Nitro, the new Nuxt rendering engine, and Nuxt Bridge. We'll explore some of the ways that you can use and deploy Nitro, whilst building a application together with some of the real-world constraints you'd face when deploying an app for your enterprise. Along the way, fire your questions at me and I'll do my best to answer them.
JSNation 2022JSNation 2022
141 min
Going on an adventure with Nuxt 3, Motion UI and Azure
WorkshopFree
We love easily created and deployed web applications! So, let’s see what a very current tech stack like Nuxt 3, Motion UI and Azure Static Web Apps can do for us. It could very well be a golden trio in modern day web development. Or it could be a fire pit of bugs and errors. Either way it will be a learning adventure for us all. Nuxt 3 has been released just a few months ago, and we cannot wait any longer to explore its new features like its acceptance of Vue 3 and the Nitro Engine. We add a bit of pizzazz to our application with the Sass library Motion UI, because static design is out, and animations are in again.Our driving power of the stack will be Azure. Azure static web apps are new, close to production and a nifty and quick way for developers to deploy their websites. So of course, we must try this out.With some sprinkled Azure Functions on top, we will explore what web development in 2022 can do.
Vue.js London 2023Vue.js London 2023
137 min
TresJS create 3D experiences declaratively with Vue Components
Workshop
- Intro 3D - Intro WebGL- ThreeJS- Why TresJS- Installation or Stackblitz setup - Core Basics- Setting up the Canvas- Scene- Camera- Adding an object- Geometries- Arguments- Props- Slots- The Loop- UseRenderLoop composable- Before and After rendering callbacks- Basic Animations- Materials- Basic Material- Normal Material- Toon Material- Lambert Material- Standard and Physical Material- Metalness, roughness - Lights- AmbientLight- DirectionalLight- PointLights- Shadows- Textures- Loading textures with useTextures- Tips and tricks- Misc- Orbit Controls- Loading models with Cientos- Debugging your scene- Performance
Vue.js London Live 2021Vue.js London Live 2021
176 min
Building Vue forms with VeeValidate
Workshop
In this workshop, you will learn how to use vee-validate to handle form validation, manage form values and handle submissions effectively. We will start from the basics with a simple login form all the way to using the composition API and building repeatable and multistep forms.

Table of contents:
- Introduction to vee-validate
- Building a basic form with vee-validate components
- Handling validation and form submissions
- Building validatable input components with the composition API
- Field Arrays and repeatable inputs
- Building a multistep form
Prerequisites:
VSCode setup and an empty Vite + Vue project.
Vue.js London Live 2021Vue.js London Live 2021
116 min
Building full-stack GraphQL applications with Hasura and Vue 3
Workshop
The frontend ecosystem moves at a breakneck pace. This workshop is intended to equip participants with an understanding of the state of the Vue 3 + GraphQL ecosystem, exploring that ecosystem – hands on, and through the lens of full-stack application development.

Table of contents
- Participants will use Hasura to build out a realtime GraphQL API backed Postgres. Together we'll walk through consuming it from a frontend and making the front-end reactive, subscribed to data changes.
- Additionally, we will look at commonly-used tools in the Vue GraphQL stack (such as Apollo Client and Urql), discuss some lesser-known alternatives, and touch on problems frequently encountered when starting out.
- Multiple patterns for managing stateful data and their tradeoffs will be outlined during the workshop, and a basic implementation for each pattern discussed will be shown.
Workshop level

NOTE: No prior experience with GraphQL is necessary, but may be helpful to aid understanding. The fundamentals will be covered.