Meilleure expérience dans la création d'applications angulaires propres et rapides

Pour écrire cet article, ils ont été encouragés par la recherche de développeurs front-end JavaScript dans leur entreprise à Stavropol. Parce que Pendant longtemps, il n'a pas été possible de trouver un programmeur intelligent, puis nous avons décidé de lancer un programme de stage avec beaucoup de matériel de formation sur Angular & JS.

Ceci est une traduction d'un article de Vamsi Vempati sur son expérience avec une application à grande échelle pour Trade Me écrite en angulaire.



À ce jour, j'ai déjà travaillé quelques années sur une application angulaire à grande échelle chez Trade Me. Au cours des dernières années, notre équipe a affiné notre application en termes de normes d'écriture de code et de performances pour la mettre au meilleur état possible.

L'article décrit les méthodes que nous utilisons dans notre projet. Le texte est principalement associé à Angular, TypeScript, RxJs et @ ngrx / store.

De plus, quelques directives générales pour l'écriture de code qui aideront à rendre l'application plus «propre» et lisible seront prises en compte.

1) trackBy


Lorsque vous utilisez ngFor pour boucler un tableau dans des modèles, reportez-vous à la fonction trackBy , qui renverra un identifiant unique pour chaque élément.

Pourquoi?


Lorsque le tableau change, Angular redessine complètement l'arborescence DOM. Mais si vous utilisez la fonction trackBy , Angular comprendra quel élément a changé, puis apportera des modifications au DOM uniquement pour cet élément particulier.

Remarque: une description plus détaillée se trouve dans l'article de Nathanel Bazal. [eng]

À


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


Après


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

2) const ou let?


Lors de la déclaration de variables, utilisez const si elles ne seront pas réaffectées.

Pourquoi?


L'utilisation de let et const, le cas échéant, rend la raison de la déclaration des variables plus compréhensible. Il peut également aider à identifier les problèmes lorsqu'une valeur est réaffectée au hasard à une constante en raison d'une erreur de compilation. Il améliore également la lisibilité du code.

À


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

Après


 //  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) Opérateurs semblables à des tuyaux


Utilisez des instructions de type pipe lorsque vous travaillez avec des RxJs .
Les opérateurs de type pipe incluent uniquement le code qui doit être exécuté lors de l'importation.

Cela facilite également la recherche d'instructions inutilisées dans les fichiers.

Remarque: Angular 5.5 et supérieur est nécessaire.

À


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

Après


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

4) Connectez-vous au modèle


Évitez de vous abonner à des objets surveillés à partir de composants - au lieu de cela, abonnez-vous à partir d'un modèle.

Pourquoi?


async flux async sont automatiquement désabonnés, ce qui simplifie le code et élimine la nécessité d'une gestion manuelle des abonnements. Le risque de désinscription accidentelle dans un composant est également réduit, ce qui entraînera une fuite de mémoire. Cela peut être résolu en utilisant la règle lint pour détecter les objets observés non signés.

De plus, il ne permet pas aux composants de rester statiques et ajoute des erreurs lorsque les données changent en dehors de l'abonnement.

À


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

Après


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

5) Effacer les abonnements


Lorsque vous vous abonnez à des objets surveillés, assurez-vous toujours de vous désabonner de manière appropriée à l'aide des opérateurs tels que take , takeUntil , etc.

Pourquoi?


Les erreurs de désinscription des objets observés entraîneront une fuite de mémoire indésirable, car le flux observé reste ouvert, probablement même après la suppression du composant ou lorsque l'utilisateur passe à une autre page.

De plus, créez une règle de lint pour détecter les objets observables à partir desquels il n'y a pas de désinscription.

À


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


Après


 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(); } 

Utilisation de takeUntil pour écouter les modifications jusqu'à ce qu'un autre objet observé renvoie une valeur:

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

Notez l'utilisation de takeUntil avec take dans l'exemple ci-dessus. Cela évite les fuites de mémoire causées par le fait qu'aucune valeur n'a été affectée à l'abonnement avant la suppression du composant.

Sans takeUntil abonnement sera toujours dans un état suspendu, jusqu'à ce qu'il reçoive sa première valeur, mais puisque le composant a déjà été supprimé, il ne recevra jamais la valeur, ce qui entraînera une fuite de mémoire.

6) Chargement paresseux


Dans la mesure du possible, essayez de charger les modules dans une application Angular uniquement lorsqu'ils sont en cours d'utilisation.

Pourquoi?


Cela réduira la taille de l'application téléchargée et raccourcira son temps de chargement.

À


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

Après


 // 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 {} 

Suite de la traduction dans le prochain article. Si quelqu'un ne veut pas attendre, voici un lien vers l'article d'origine.

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


All Articles