Comment 'Tuner' votre Projet Angular

  • posté le
  • par ESENS
' Tout va vite de nos jours '

Il n’est pas forcément de très bon goût de citer son grand-père comme propos liminaires d’une présentation technique sur un framework JavaScript, mais face à ce poncif dont la réalité implacable s’impose à nous tous, tantôt subite, tantôt désirée, il n’en reste pas moins que la tendance ne va pas à la décélération.

Fort de ce constat (légèrement excessif), il est alors légitime de se poser la question ' est-ce que ça va vite Angular dites donc ? '.

Une première réponse nous est apportée par le tableau ci-dessous :



Nous voyons que Angular est très performant. Nous remercions le lecteur pour sa lecture attentive.

Proposons tout de même quelques pistes d’amélioration dans le cas où une application rencontrerait des lenteurs.

Compilation AoT vs JiT

La compilation ahead of time (AoT) est un mécanisme permettant de générer tout un ensemble de code (dont les fameuses factory.js, les AST etc.) au moment du build de votre projet que ce soit sur le serveur ou sur une plateforme d’intégration contrairement au mode just in time (JiT) qui délègue ces étapes de compilation (dites dynamiques) et parsing au navigateur.

La version d’Angular 6 approchant à grands pas va apporter la consécration de ce mode de compilation en la rendant par défaut. Pour le moment, un petit rappel s’impose :

  • ng build et ng serve sont en JiT
  • ng build --aot et ng serve --aot ou ng build --prod et ng serve --aot sont en AoT

Quelques mises en garde s’imposent. La mise en place de l’AoT déplaçant la phase de compilation hors du navigateur, il est nécessaire lors des développements d’appliquer les bons modificateurs. Par exemple, un data-binding fait dans le template HTML ne pourra pas référencer une propriété private :


Mettre à jour Angular

Eh bien oui ! Angular est encore un framework tout jeune, ce qui fait que chaque mise à jour apporte son lot d’améliorations de performance. Même avec une fréquence de release de 6 mois, il n'existe que peu de ruptures de compatibilités limitant une montée régulière de version. Il ne faut donc pas hésiter !

Le 'lazy loading' de module

Il est possible, depuis Angular 2, de créer des feature modules, comprenez sous ensembles logiques représentant un aspect fonctionnel. Ce mode de compartimentalisation couplé avec un  routage embarqué permet de mettre en place le mécanisme de lazy loading de module par routage.  

Lorsque des modules sont présents, ils ne sont chargés que lorsque la navigation, déclenchée par le routeur de l’application, cible un composant présent dans ce module.  

Dès lors, le processus de bootstrapping de l’application s’en voit nettement accéléré puisque le chargement initial se limite uniquement aux composants nécessaires.  

Pour en savoir plus, la documentation officielle.

Routeur embarqué dans un module

Optimiser les imports

Connaissez-vous Rxjs ? Depuis Angular 2, la gestion des évènement asynchrones se base sur l’implémentation du pattern Observable fournie par Rxjs.


Une bonne manière d’optimiser la taille du code livré est d’importer strictement depuis Rxjs les classes et opérateurs nécessaires. Il en va de même pour les bibliothèques modulaires importables qui permettent de n’empaqueter que les modules nécessaires. Par exemple @angular/material est devenu modulaire pour ce faire depuis la 2.0.0-beta.11  

Par ailleurs, l’utilisation de Webpack et par extension de angular-cli permet d’utiliser les mécanismes de tree shaking (à ne pas confondre avec l’élagage du code mort) qui consiste à l’élimination du code non appelé des bibliothèques importées après sa minification, améliorant une fois de plus la taille du livrable.  

Des outils sont également disponibles pour surveiller la taille du code livré au build et détecter les librairies embarquées dans le projet : source-map-explorer ou webpack-bundle-analyzer.

Capture d'écran de webpack-bundle-analyzer

Changer de bundler


Si vous utilisez angular-cli, vous devez probablement savoir (dans le cas échéant vous voilà prévenu J) que ce dernier utilise Webpack comme bundler pour les tâches de minification, concaténation, uglyfication lors du build (faut arrêter Gulp hein). Mais une alternative pointe son nez : Bazel, version open-source du logiciel interne de build et de bundling Blaze développé par Google. Il a pour avantage de faire des builds incrémentaux !

Change detection

Le processus de change detection est le mécanisme implémenté par Angular servant à détecter les modifications et changements nécessitant la mise à jour du modèle et de la vue d’un ou plusieurs composants. Bien heureux de bénéficier de ce mécanisme (sans lequel nous n’aurions pas de data binding), il est intéressant d’en connaître ses méandres pour l’optimiser.  

Commençons par lister ce qui peut déclencher  zone.js et pousser à déclencher une boucle de vérification de changement, on retrouve :

  • Events utilisateur : Click utilisateurs, submit de formulaire, saisie clavier…
  • XHR : Appels Ajax
  • Timers : setTimeout(), setInterval()

Que se passe-t-il après détection d’un évènement ? Eh bien connaissant la structure arborescente des composants Angular, cet évènement sera propagé de manière descendante depuis le composant racine vers les feuilles de l’arbre forçant sur son passage le re-rendering de chacun des composants traversés.


Pour pallier à ce phénomène de propagation, Angular met à disposition la modification de la stratégie de la détection pour chaque composant.  

Ainsi la stratégie dite OnPush permet de ne déclencher une passe de re-rendering que si un changement est détecté sur une entrée du composant.



Il est par ailleurs possible de déclarer un composant comme non disposé à la détection de changement et cela programmatiquement. Pour ce faire, Angular met également à disposition le ChangeDetectorRef pour chaque composant par injection.  

Dès lors il est possible grâce à la méthode detach() de retirer un composant de l’arbre de détection et manuellement d’enclencher un re-rendering si besoin est avec la méthode detectChanges()



Finalement, pour redéclencher la mise-à-jour sur le composant, nous avons la méthode markForCheck()

Pour terminer et en guise de conclusion, ces mécanismes ne doivent être utilisés que lorsque votre application rencontre des lenteurs insurmontables, sans quoi il est préférable de ne pas toucher aux rouages internes du framework pour ne pas tout casser ! Par exemple, une modification fortuite et non contrôlée du ChangeDetector peut provoquer des bugs conséquents comme pas de détection du tout...

Article rédigé par Simon | Retrouvez tous nos articles sur le Blog ESENS !


Vous êtes à la recherche d'un nouveau challenge ? Rejoignez l'équipe ESENS en postulant à nos offres d'emploi !

PARTAGER CET ARTICLE