Usa React.lazy con confianza: Una forma segura de cargar componentes cuando se itera rápidamente
React.lazy es una excelente manera de cargar componentes bajo demanda y mejorar el rendimiento de tu aplicación. Sin embargo, a veces puede causar algunos problemas como "ChunkLoadError" y "Loading chunk failed".
El dilema
Hoy en día, el desarrollo de software se mueve más rápido bajo la popular filosofía de "moverse rápido y romper cosas". No es un juicio, simplemente es así. Sin embargo, este ritmo acelerado a veces puede llevar a problemas, especialmente cuando se trata de cargar componentes en React.
Si estás trabajando en un proyecto que usa React.lazy para cargar componentes bajo demanda, es posible que hayas encontrado algunos problemas como ChunkLoadError
y Loading chunk failed
. Aquí hay algunas posibles razones:
- Hay un problema de red, por ejemplo, la conexión a internet del usuario es lenta o inestable.
- El usuario está en una versión obsoleta de la aplicación, y el navegador está tratando de cargar un fragmento que ya no existe.
Usualmente, una simple actualización de la página puede resolver el problema, pero no es una gran experiencia para el usuario. Imagina si aparece una pantalla en blanco cuando el usuario navega a otra ruta - no es una buena imagen para tu aplicación.
¿Podemos equilibrar la necesidad de velocidad con la necesidad de una experiencia de usuario fluida? Claro. Déjame mostrarte cómo (con TypeScript, por supuesto).
La solución
Una solución de fuerza bruta podría ser guardar todas las versiones de los fragmentos en el servidor, evitando así el problema del "fragmento faltante". A medida que tu aplicación crece, esta solución puede volverse inviable debido al aumento de los requerimientos de espacio en disco, y aún no resuelve el problema de la red.
Dado que un reinicio o una actualización pueden resolver el problema, podemos implementar estas soluciones en nuestro código. Como el problema generalmente ocurre cuando el usuario navega a otra ruta, podemos solucionarlo incluso sin que el usuario lo note. Todo lo que necesitamos hacer es construir un contenedor alrededor de la función React.lazy
que maneje los reintentos y las actualizaciones.
Ya existen algunos artículos excelentes sobre cómo implementar este tipo de solución, así que me enfocaré en la idea y el funcionamiento interno de la solución.
Crear el contenedor
El primer paso es crear un contenedor alrededor de la función React.lazy
:
Manejar los reintentos
Para los problemas de red, podemos manejar los reintentos envolviendo el importFunction
en una función tryImport
:
Parece simple, ¿verdad? También puedes implementar el algoritmo de exponential backoff para manejar los reintentos de manera más eficiente.
Manejar las actualizaciones
Para el problema de la versión obsoleta, podemos manejar las actualizaciones atrapando el error y refrescando la página:
Sin embargo, esta implementación es muy peligrosa, ya que puede causar un bucle infinito de actualizaciones cuando el error no puede solucionarse con una actualización. Mientras tanto, el estado de la aplicación se perderá durante la actualización. Así que necesitamos la ayuda de sessionStorage
para almacenar el mensaje de que hemos intentado actualizar la página:
Ahora, cuando atrapemos el error desde la función safeLazy
, sabremos que es algo que no puede resolverse con una actualización.
Múltiples componentes lazy en la misma página
Todavía hay una trampa oculta en la implementación actual. Si tienes múltiples componentes lazy en la misma página, el bucle infinito de actualizaciones aún puede ocurrir porque otros componentes pueden restablecer el valor de sessionStorage
. Para resolver este problema, podemos usar una clave única para cada componente:
Ahora, cada componente tendrá su propia clave en sessionStorage
, y se evitará el bucle infinito de actualizaciones. Podemos seguir afinando la solución, por ejemplo:
- Reunir todas las claves en un array, de modo que solo se necesite una clave de almacenamiento.
- Establecer un límite de actualización para actualizar la página más de una vez antes de lanzar un error.
Pero creo que ya tienes la idea. Una solución completa en TypeScript con pruebas y configuraciones está disponible en el repositorio de GitHub. También he publicado el paquete react-safe-lazy
en NPM, por lo que puedes usarlo en tu proyecto de inmediato.
Conclusión
El desarrollo de software es un trabajo delicado, y hasta los pequeños detalles pueden requerir esfuerzo para resolverse. Espero que este artículo te ayude a manejar con gracia los problemas con React.lazy
y mejorar la experiencia de usuario de tu aplicación.