Optimizando Angular JS

  • por Francisco Vallés

Angular JS es un gran framework que tiene muchas funcionalidades, pero lo que se le ha criticado siempre es los problemas de rendimiento que puede llegar a tener. Por este motivo, les dejo algunos consejos para optimizar un poco más las aplicaciones hechas con angular.

No utilizar el two-way binding cuando no es necesario

Angular se vuelve más lento cuando hay alrededor de 2.000 watchers, lo cuales se revisan en cada digest cycle, menoscavando la usabilidad para los usuarios de la aplicación. Es por esto que lo mejor en minimizar la cantidad de los mismos. Una de las manera de hacer esto, es limitar las variables que no requieran actualización a one-way binding de la siguiente manera:

{{::variable}}

Minimizar el uso de ng-repeat

La directiva ng-repeat crea un scope por cada ítem que genera, agregando muchos watchers. Este problema se hace más notorio cuando se usa la directiva para mostrar una lista grande de elementos. Además, si dentro del ng-repeat tenemos otras directivas como un ng-show por ejemplo, la cantidad de watchers se multiplica.

Para reducir los problemas de rendimiento, es bueno utilizar track by, lo cual permite identificar únicamente los ítems que se están mostrando actualmente y no tener que volver a generarlos frente a cambios. Sumado a lo anterior, es bueno hacer uso de infinite scrolling o algún tipo de paginado, que nos permite cargar de manera gradual los ítems a medida que necesitamos mostrarlos. Para lo último, se pueden utilizar directivas como ngInfiniteScroll u ocupar las funcionalidades que vienen por defecto en frameworks como Ionic.

Limitar los filtros en el DOM

Los filtros de Angular JS son una funcionalidad muy útil, pero hay que tener en cuenta que estos se ejecutan 2 veces por cada digest cycle. Para evitar esto, simplemente podemos escribirlos en el controlador de la siguiente manera:

$filter('filter')(array, expression, comparator)

Debounce ngmodel

En el caso en que se use ng-model en alguna variable que sabemos que va a cambiar constantemente, para evitar ejecutar el digest cycle cada vez que haya un cambio, podemos utilizar la siguiente directiva para que este no se ejecute más de 1 vez cada Xms:

 ng-model-options="{ debounce: X }

Un ejemplo típico sería el caso de un buscador, en el que cada caracter que se escribe ejecuta el digest cycle.

Usar ng-if en vez de ng-show si este último no es necesario

Hay una diferencia entre ambas directivas, ya que ng-show/ng-hide lo que hace es cambiar el atributo de estilo display de los elementos en cuestión, mientras que ng-if agrega o quita los elementos del DOM. Esto es relevante ya que al quitar los elementos del DOM, también se quitan sus watchers asociados, por lo que al ejecutarse el digest cycle este demora menos.

Mejorar bucles

Todo el código que pueda dejarse fuera de un bucle, como un clásico for, mejora el rendimiento de la aplicación. Sigue la misma lógica que los ng-repeat, ya que el código que esté dentro, se ejecutará un número n de veces, las cuales pueden ser innecesarias. Esto incluye también, la definición del número de veces que se ejecutará el bucle, el cual no debe ser definido mediante una función, sino que mediante una variable.

Mal ejemplo:

var sum = 0;
for(var x = 0; x < array.length; x++){
  var keys = Object.keys(obj);
  sum = sum + keys[x];
}

Ejemplo mejorado:

var sum = 0;
var keys = Object.keys(obj);
var length = array.length;
for(var x = 0; x < length; x++){
  sum = sum + keys[x];
}

Nunca binding a una función ni a un resultado de una, siempre a variables

Esto es importante, ya que si hacemos binding a una función en un ng-repeat o ng-show, por ejemplo, esta se llamará cada vez que se ejecute el digest cycle, ralentizando la aplicación.

Utilizar herramientas para medir el rendimiento de la aplicación

Console.time es una API que permite de manera simple, medir el tiempo que demora cierto trozo de código. Un ejemplo a continuación:

console.time("TimerName");
setTimeout(function(){
    console.timeEnd("TimerName");
}, 100);
//In console $: TimerName: 100.324ms

Batarang es una extensión de las herramientas de desarrollo de Chrome, que nos permite ver los scopes anidados y el rendimientos de las distintas expresiones de la aplicación.

Chrome Timeline es otra herramienta útil, y nos permite ver cuánto se demora la aplicación en cargar, pudiendo identificar las funciones que consumen mayor tiempo. Todo esto de manera muy específica, por lo que uno puede identificar el código que está produciendo problemas.

 

 

Fuentes: