Angular es un popular framework front-end que permite a los desarrolladores crear aplicaciones web dinámicas de forma eficiente. Sin embargo, no es raro que las aplicaciones sufran problemas de rendimiento debido a malas prácticas de desarrollo. Optimizar el rendimiento de las aplicaciones Angular es fundamental para ofrecer una experiencia de usuario fluida, especialmente a medida que aumenta la complejidad de la aplicación.
En este artículo, exploraremos las prácticas comunes que degradan el rendimiento en aplicaciones Angular y cómo puedes evitarlas para asegurarte de que tu app funcione sin problemas.
1. Detección de cambios ineficiente
Angular utiliza un mecanismo de detección de cambios para realizar un seguimiento de los cambios de datos y actualizar la vista en consecuencia. Por defecto, la detección de cambios de Angular se ejecuta en cada evento del navegador, como clics, peticiones HTTP e incluso funciones setTimeout
. Este mecanismo puede ser costoso si no se optimiza.
Problema
- Actualizaciones frecuentes: Si tu aplicación tiene muchos componentes, la detección de cambios de Angular se activará para cada uno de ellos, incluso si el estado de un componente no ha cambiado.
- Golpe al rendimiento: Esto lleva a recálculos innecesarios, ralentizando la aplicación.
Solución
- Utilizar la estrategia de detección de cambios
OnPush
siempre que sea posible. Esto le dice a Angular que sólo ejecute la detección de cambios cuando las propiedades de entrada de un componente cambien.
@Component({ selector: 'app-example', changeDetection: ChangeDetectionStrategy.OnPush })
- Aproveche
la tubería asíncrona
para gestionar las suscripciones de forma eficaz en las plantillas.
<div *ngFor="let item of items$ | async"> {{ item.name }} </div>
2. Bibliotecas de terceros no optimizadas
Las bibliotecas de terceros se utilizan ampliamente para ampliar la funcionalidad. Sin embargo, no todas las bibliotecas están optimizadas para el rendimiento, y su uso descuidado puede conducir a la hinchazón del paquete y al comportamiento lento de la aplicación.
Problema
- Algunas bibliotecas cargan código innecesario, aumentando el tamaño del paquete JavaScript, lo que afecta a los tiempos de carga iniciales y al uso de la memoria.
Solución
- Importa de las bibliotecas sólo lo que necesites. Utiliza importaciones de árbol para eliminar el código no utilizado.
import { specificFunction } from 'heavy-library';
- Audite regularmente sus dependencias y elimine las bibliotecas no utilizadas utilizando herramientas como Webpack Bundle Analyzer.
3. Ignorar la carga lenta
Lazy loading permite cargar los módulos de la aplicación sólo cuando es necesario, mejorando el tiempo de carga inicial al dividir la aplicación en trozos más pequeños. No implementar la carga perezosa para aplicaciones grandes es un error común que conduce a un rendimiento pobre.
Problema
- Si todos los componentes se cargan por adelantado, los usuarios deben esperar más tiempo para que la página sea interactiva.
Solución
- Implementar lazy loading para módulos de características utilizando la configuración del router de Angular.
const routes: Routes = [ { path: 'dashboard', loadChildren: () => import('./dashboard/dashboard.module').then(m => m.DashboardModule) } ];
- Considere la posibilidad de utilizar la precarga de rutas para las rutas clave con el fin de lograr un equilibrio entre el rendimiento y la experiencia del usuario.
4. Uso excesivo de Watchers
La vinculación de datos bidireccional de Angular puede dar lugar a la creación de numerosos observadores para supervisar los cambios. Esto puede causar importantes cuellos de botella en el rendimiento si no se maneja con cuidado, especialmente en aplicaciones grandes.
Problema
- Demasiados watchers ralentizan la detección de cambios, ya que Angular tiene que evaluar cada watcher durante cada ciclo.
Solución
- Limitar la vinculación de datos bidireccional y, en su lugar, utilizar la vinculación de datos unidireccionalsiempre que sea posible. Por ejemplo, utiliza
[property]
en lugar de[(ngModel)]
para el contenido estático. - Evite crear watchers en plantillas anidadas complejas. Reduzca la vinculación cuando sea innecesaria o utilice la detección de cambios independiente para componentes específicos.
5. No optimizar para producción
Ejecutar aplicaciones Angular en modo de desarrollo durante la producción puede tener implicaciones significativas en el rendimiento porque Angular realiza comprobaciones y registros adicionales en modo de desarrollo.
Problema
- Ejecutar en modo desarrollo aumenta los tiempos de carga y degrada el rendimiento.
Solución
- Construye siempre tu app usando la bandera de producción para habilitar optimizaciones como la compilación AOT (Ahead-Of-Time) y la minificación.
ng build --prod
6. Descuidar la compilación Ahead-Of-Time (AOT)
El uso de la compilación Just-In-Time (JIT ) en Angular tiene como resultado un menor rendimiento de la aplicación, ya que compila la aplicación en el navegador. AOT precompila la aplicación durante el proceso de compilación, reduciendo el trabajo que debe realizarse en tiempo de ejecución.
Problema
- La compilación JIT aumenta el tamaño de los paquetes y ralentiza la carga y ejecución de la aplicación.
Solución
- Utilice la compilación AOT para reducir el tamaño de los paquetes y mejorar el rendimiento. Esto se puede activar utilizando la bandera - aot al compilar la aplicación.
ng build --prod --aot
7. Ignorando Fugas de Memoria
Las fugas de memoria se producen cuando los componentes o servicios de Angular no se destruyen correctamente. Esto puede ocurrir si dejas suscripciones activas o los elementos DOM no se limpian correctamente.
Problema
- Las fugas de memoria conducen a un mayor consumo de memoria y, finalmente, bloquean la aplicación.
Solución
- Desuscribirse siempre de Observables en
ngOnDestroy()
o utilizar latubería async
.
ngOnDestroy() { this.subscription.unsubscribe(); }
- Utiliza los mecanismos de limpieza incorporados en Angular, como trackBy para las directivas
ngFor
para optimizar la manipulación del DOM y el uso de memoria.
8. Renderizado ineficiente de plantillas
El motor de plantillas de Angular es rápido, pero las prácticas de renderizado ineficientes pueden causar cuellos de botella en el rendimiento. Por ejemplo, usar métodos caros dentro de una expresión de plantilla puede ralentizar el renderizado.
Problema
- Si se llama a un método dentro de una plantilla, se ejecutará cada vez que se active la detección de cambios, lo que provocará problemas de rendimiento
Solución
- Evite llamar a métodos dentro de las plantillas. En su lugar, calcule valores fuera de la plantilla y asígnelos a variables.
<!-- Bad Practice --> <p>{{ calculateHeavyOperation() }}</p> <!-- Good Practice --> <p>{{ cachedValue }}</p>
Conclusión
Optimizar las aplicaciones Angular es crucial para ofrecer experiencias de usuario rápidas y con capacidad de respuesta. Al abordar las prácticas comunes anteriores que matan el rendimiento, puede asegurarse de que su aplicación Angular escala de manera eficiente y funciona bien en diversas condiciones.