La mejor experiencia en la creación de aplicaciones angulares limpias y rápidas

Para escribir este artículo, fueron alentados por la búsqueda de desarrolladores front-end de JavaScript en su empresa en Stavropol. Porque Durante mucho tiempo no fue posible encontrar un programador inteligente, y luego decidimos lanzar un programa de pasantías con mucho material de capacitación sobre Angular y JS.

Esta es una traducción de un artículo de Vamsi Vempati sobre su experiencia con una aplicación a gran escala para Trade Me escrita en Angular.



Hasta la fecha, ya he trabajado un par de años en una aplicación angular a gran escala en Trade Me. En los últimos años, nuestro equipo ha refinado nuestra aplicación en términos de estándares de escritura de código y rendimiento para llevarla al mejor estado posible.

El artículo describe los métodos que usamos en nuestro proyecto. El texto está asociado principalmente con Angular, TypeScript, RxJs y @ ngrx / store.

Además, se considerarán algunas pautas generales para escribir código que ayudarán a que la aplicación sea más "limpia" y legible.

1) trackBy


Cuando use ngFor para recorrer una matriz en plantillas, consulte la función trackBy , que devolverá un identificador único para cada elemento.

Por qué


Cuando la matriz cambia, Angular vuelve a dibujar el árbol DOM por completo. Pero si utiliza la función trackBy , Angular comprenderá qué elemento ha cambiado y luego realizará cambios en el DOM solo para ese elemento en particular.

Nota: se puede encontrar una descripción más detallada en el artículo de Nathanel Bazal. [eng]

A


 <li *ngFor="let item of items;">{{ item }}</li> 


Despues


 //   <li *ngFor="let item of items; trackBy: trackByFn">{{ item }}</li> //   trackByFn(index, item) { return item.id; // unique id corresponding to the item } 

2) const o let?


Al declarar variables, use const si no se reasignarán.

Por qué


El uso de let y const cuando sea apropiado hace que la razón para declarar variables sea más comprensible. También puede ayudar a identificar problemas en los que un valor se reasigna aleatoriamente a una constante debido a un error en tiempo de compilación. También mejora la legibilidad del código.

A


 let car = 'ludicrous car'; let myCar = `My ${car}`; let yourCar = `Your ${car}`; if (iHaveMoreThanOneCar) { myCar = `${myCar}s`; } if (youHaveMoreThanOneCar) { yourCar = `${youCar}s`; } 

Despues


 //  car  ,      (const) const car = 'ludicrous car'; let myCar = `My ${car}`; let yourCar = `Your ${car}`; if (iHaveMoreThanOneCar) { myCar = `${myCar}s`; } if (youHaveMoreThanOneCar) { yourCar = `${youCar}s`; } 

3) operadores tipo tubería


Use declaraciones tipo tubería cuando trabaje con RxJs .
Los operadores tipo tubería incluyen solo el código que debe ejecutarse al importar.

También facilita la búsqueda de declaraciones no utilizadas en los archivos.

Nota: Se necesita Angular 5.5 y superior.

A


 import 'rxjs/add/operator/map'; import 'rxjs/add/operator/take'; iAmAnObservable .map(value => value.item) .take(1); 

Despues


 import { map, take } from 'rxjs/operators'; iAmAnObservable .pipe( map(value => value.item), take(1) ); 

4) Inicie sesión en la plantilla


Evite suscribirse a objetos monitoreados desde componentes; en cambio, suscríbase a ellos desde una plantilla.

Por qué


async feeds async se anulan automáticamente, lo que simplifica el código y elimina la necesidad de una administración de suscripción manual. El riesgo de darse de baja accidental en un componente también se reduce, lo que provocará una pérdida de memoria. Esto se puede solucionar mediante el uso de la regla de pelusa para detectar objetos observados sin firmar.

Además, no permite que los componentes permanezcan estáticos y agrega errores cuando los datos cambian fuera de la suscripción.

A


 //  <p>{{ textToDisplay }}</p> //  iAmAnObservable .pipe( map(value => value.item), takeUntil(this._destroyed$) ) .subscribe(item => this.textToDisplay = item); 

Despues


 //  <p>{{ textToDisplay$ | async }}</p> //  this.textToDisplay$ = iAmAnObservable .pipe( map(value => value.item) ); 

5) Borrar suscripciones


Al suscribirse a objetos monitoreados, siempre asegúrese de darse de baja de ellos de manera adecuada utilizando operadores como take , takeUntil , etc.

Por qué


Los errores derivados de la cancelación de la suscripción de objetos observados conducirán a una pérdida de memoria no deseada, ya que la secuencia observada permanece abierta, probablemente incluso después de que se elimina el componente o cuando el usuario se mueve a otra página.

Además, cree una regla de lint para detectar objetos observables de los que no se puede cancelar la suscripción.

A


 iAmAnObservable .pipe( map(value => value.item) ) .subscribe(item => this.textToDisplay = item); 


Despues


 private _destroyed$ = new Subject(); public ngOnInit (): void { iAmAnObservable .pipe( map(value => value.item) //     iAmAnObservable   ,     / takeUntil(this._destroyed$) ) .subscribe(item => this.textToDisplay = item); } public ngOnDestroy (): void { this._destroyed$.next(); this._destroyed$.complete(); } 

Usando takeUntil para escuchar los cambios hasta que otro objeto observado devuelva un valor:

 iAmAnObservable .pipe( map(value => value.item), take(1), takeUntil(this._destroyed$) ) .subscribe(item => this.textToDisplay = item); 

Tenga en cuenta el uso de takeUntil junto con take en el ejemplo anterior. Esto evita pérdidas de memoria causadas por el hecho de que no se asignó ningún valor a la suscripción antes de que se eliminara el componente.

Sin takeUntil suscripción seguirá en estado suspendido, hasta que reciba su primer valor, pero dado que el componente ya se ha eliminado, nunca recibirá el valor, y esto provocará una pérdida de memoria.

6) carga perezosa


Siempre que sea posible, intente cargar módulos en una aplicación Angular solo cuando estén en uso.

Por qué


Esto reducirá el tamaño de la aplicación descargada y acortará su tiempo de carga.

A


 // app.routing.ts { path: 'not-lazy-loaded', component: NotLazyLoadedComponent } 

Despues


 // app.routing.ts { path: 'lazy-load', loadChildren: 'lazy-load.module#LazyLoadModule' } // lazy-load.module.ts import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { RouterModule } from '@angular/router'; import { LazyLoadComponent } from './lazy-load.component'; @NgModule({ imports: [ CommonModule, RouterModule.forChild([ { path: '', component: LazyLoadComponent } ]) ], declarations: [ LazyLoadComponent ] }) export class LazyModule {} 

Traducción continua en el próximo artículo. Si alguien no quiere esperar, aquí hay un enlace al artículo original.

Source: https://habr.com/ru/post/447042/


All Articles