Jason Miller | Scaling Vite at Shopify | ViteConf 2024

Jason Miller | Scaling Vite at Shopify | ViteConf 2024

Escalando Vite en Shopify

Introducción a la migración de Webpack a Vite

  • Jason Miller presenta su experiencia trabajando con el mayor código base de React en Shopify, que anteriormente utilizaba Webpack y tenía 5 millones de líneas de TypeScript y 800 rutas.
  • La aplicación era demasiado grande y lenta para ejecutarse eficientemente en máquinas locales y durante las integraciones continuas (CI), lo que dificultaba el trabajo.

Beneficios de la migración a Vite

  • Tras migrar a Vite, la aplicación se convirtió en una SPA (Single Page Application) utilizando Remix, mejorando significativamente la velocidad del desarrollo local.
  • Se eliminaron transformaciones personalizadas para evitar costos adicionales asociados con Babel, lo que optimizó el rendimiento general.

Plugins personalizados para mejorar la funcionalidad

  • Se desarrollaron varios plugins personalizados para facilitar características como módulos CSS por defecto, carga de traducciones y generación de tipos GraphQL.
  • Estos plugins no solo mejoraron el rendimiento sino que también permitieron realizar pruebas más eficientes en producción.

Problemas iniciales tras la migración

  • Al cambiar a Vite, se encontraron con un problema inesperado: al cargar la página principal se enviaban 18,000 módulos al navegador, lo que resultaba en tiempos de carga prolongados.
  • A pesar del tiempo de carga elevado, los recargas calientes eran rápidas (un segundo), pero surgieron dudas sobre el manejo eficiente de los módulos.

Desafíos relacionados con archivos barrel

  • Los archivos barrel (módulos JavaScript que re-exportan otros módulos) causaron problemas significativos. Aunque organizaban el código base, generaban confusión y complicaciones.
  • Se identificó un problema relacionado con la eliminación del código muerto; algunos módulos no podían ser eliminados debido a referencias desconocidas dentro del bundle.

Impacto negativo en claridad y mantenimiento

  • La falta de claridad derivada del uso extensivo de archivos barrel complicó el proceso para identificar las fuentes originales de las importaciones.

Problemas de Re-exportación en Módulos

Importaciones y Re-exportaciones

  • La re-exportación de módulos puede llevar a confusiones sobre el valor final de una exportación. No es suficiente con que un módulo exporte A; se debe considerar la última re-exportación que define su valor.

Ciclos de Importación Accidentales

  • Se presentan ciclos de importación accidentales cuando un módulo intenta referirse a otro antes de haber sido completamente ejecutado, lo que resulta en valores indefinidos.

Estrés en la Infraestructura

  • Los ciclos de importación aumentan la carga en la infraestructura, incrementando el uso de memoria y el tiempo de servicio al requerir más archivos y módulos desde el disco.

Código de Prueba en Producción

Problemas con Ayudantes de Pruebas

  • Al re-exportar ayudantes para pruebas desde archivos barrel, se corre el riesgo de incluir código no deseado en producción debido a la eliminación ineficaz del código muerto.

Archivos Binarios y Lazy Loading

Archivos Barrel vs. JavaScript Real

  • Algunos archivos que comenzaron como barrels pueden convertirse en simples módulos JavaScript, complicando su gestión y análisis.

Impacto del Lazy Loading

  • El uso excesivo del lazy loading puede transformar módulos estáticos en dinámicos, dificultando su identificación como barrels válidos.

Limitaciones del Linting

Desempeño del Linter

  • Los linters pueden volverse muy lentos al intentar realizar análisis exhaustivos sobre las importaciones, lo cual afecta significativamente los tiempos de CI.

Soluciones Propuestas

  • Se sugiere utilizar un plugin llamado "debarrel" para optimizar las importaciones durante el proceso de entrega al navegador, mejorando así la eficiencia general.

Optimización mediante Debarreling

Reducción Significativa en Carga Inicial

  • Implementar el plugin "debarrel" ha permitido reducir más del 50% tanto el número total de módulos servidos como el tiempo necesario para cargar la página inicial.

Eliminación Efectiva de Código Muerto

  • Al eliminar archivos barrel innecesarios, se facilita la identificación y eliminación del código muerto que solo era referenciado a través de estas re-exportaciones.

Mejora en Tiempos de Carga

Desacoplamiento Crítico entre UI y Lógica

Contexto de la Aplicación y React Router 6

Introducción al contexto de la aplicación

  • El contexto de la aplicación es un objeto que existe fuera del árbol de React, donde se gestionan preocupaciones globales antes de cargar el árbol de React.
  • Se utiliza Preact Signals para reactividad, permitiendo que esta no dependa de un marco específico de UI.

Carga y ejecución paralela

  • La carga de datos ocurre rápidamente con una mínima cantidad de JavaScript, funcionando como un "bootloader" en paralelo con el código más pesado relacionado con la UI.
  • La estructura del gráfico del módulo incluye importaciones dinámicas para los componentes relacionados con renderizado y enrutamiento.

Problemas con Vite/Rollup

Desafíos en la gestión de módulos

  • Los módulos comunes tienden a ser empujados hacia el módulo principal, lo que puede causar ciclos de importación problemáticos.
  • Cambios en las rutas o cargadores pueden invalidar todo el gráfico debido a dependencias estáticas entre los módulos.

Soluciones implementadas

  • Se decidió que el módulo principal nunca debe ser importado por otros módulos para evitar ciclos.
  • Se utilizan "chunks" manuales para organizar mejor las dependencias compartidas y prevenir cascadas indeseadas.

Optimización y Control del Proceso

Estrategias para mantener integridad del código

  • Implementación de un plugin Vite que verifica las dependencias críticas antes de finalizar los paquetes.
  • Si se detectan dependencias relacionadas con UI en los "chunks" críticos, se detiene la construcción.

Resultados obtenidos

  • Reducción significativa en el número total de módulos, pasando de 6,000 a 2,300 mediante reorganización.

Impacto Cultural y Mejora en Desarrollo

Cambios en la cultura organizacional

  • La nueva infraestructura permite un inicio rápido del servidor (15 segundos), eliminando construcciones previas pesadas.

Innovaciones tecnológicas

Comparativa entre Webpack y Vite

Eficiencia en el reemplazo de módulos en caliente (HMR)

  • Se menciona que la configuración local con datos de producción y el reemplazo de módulos en caliente es sorprendentemente más rápida, siendo diez veces más eficiente que métodos anteriores.
  • En una demostración, se compara la configuración de Webpack del año pasado con la actual de Vite. Al guardar un archivo, el HMR en Vite toma solo cinco milisegundos, mientras que en Webpack tarda aproximadamente 12 segundos.
  • La comparación no solo resalta las diferencias entre Webpack y Vite, sino que también enfatiza cómo Vite ha sido fundamental para habilitar mejoras significativas en el flujo de trabajo.
  • La rapidez del proceso con Vite permite a los desarrolladores trabajar de manera más eficiente al editar archivos sin interrupciones prolongadas.
Video description

Lessons learned from migrating Shopify's largest frontend codebase to Vite. https://ViteConf.org hosted by https://StackBlitz.com