Angular

Angular performance et clean code : quand le dépannage devient de l’architecture

Les 10 erreurs qui transforment une application Angular en cauchemar de maintenance, et comment les corriger : change detection, OnPush, RxJS, lazy loading et architecture.

Illustration : un code Angular emmêlé transformé en arbre de composants clair
Lexique
Change detection

Mécanisme par lequel Angular vérifie les données et met à jour le DOM.

OnPush

Stratégie de détection de changements qui ne revérifie un composant que si ses inputs changent ou si un événement le concerne.

ChangeDetectionStrategy.Default

Stratégie par défaut qui revérifie tout l’arbre de composants à chaque cycle, coûteuse sur les grosses pages.

Zone.js

Bibliothèque qui intercepte les tâches asynchrones pour déclencher la détection de changements.

Signals

Primitives réactives d’Angular qui permettent des mises à jour fines, sans revérifier tout l’arbre.

Container / presentational

Séparation entre composants qui gèrent données et état (container) et composants purement d’affichage (presentational).

NgRx

Bibliothèque de gestion d’état inspirée de Redux : store, actions, reducers, selectors, effects.

RxJS

Bibliothèque de programmation réactive à base d’Observables, au cœur d’Angular.

Lazy loading

Chargement d’un module ou d’une route uniquement lorsqu’on en a besoin, pour alléger le bundle initial.

Pipe pur

Pipe recalculé uniquement quand ses entrées changent, à préférer aux appels de fonctions dans les templates.

trackBy / track

Identifiant d’élément qui évite de recréer tout le DOM d’une liste à chaque changement.

Directive structurelle

Directive qui modifie la structure du DOM (*ngIf, *ngFor), remplacée par @if et @for depuis Angular 17.

La performance des applications Angular n’est pas un luxe, mais une nécessité. Dans un monde où chaque milliseconde compte, une application lente peut faire fuir les utilisateurs, ternir l’image de marque et compromettre les objectifs métiers.

Angular, en tant que framework riche et puissant, est souvent au cœur de la création d’applications complexes. Cependant, mal utilisé, il peut facilement devenir une source de problèmes : ralentissements, surcoûts techniques et difficulté à maintenir le code. Ces problèmes sont souvent dus à une méconnaissance des bonnes pratiques et à un écart avec les principes fondamentaux du Clean Code.

Cet article vise à sensibiliser sur l’importance d’un code propre et performant en Angular, tout en mettant en lumière les erreurs fréquentes à éviter.

Performance et clean code : un lien indissociable

La performance des applications est intimement liée à la qualité du code écrit. Un code propre, lisible et bien structuré n’est pas seulement agréable à lire : il est aussi essentiel pour garantir des applications performantes et évolutives.

  • Respecter le Clean Code permet d’optimiser naturellement la performance en minimisant les effets de bord (side effects) et en simplifiant la détection des changements.
  • En Angular, chaque décision technique joue un rôle crucial, de l’architecture des composants à la gestion des dépendances.

« Un code propre est simple et direct. Un clean code est concentré. Chaque mot compte. » – Robert C. Martin, Clean Code

Les trois catégories d’erreurs qui dégradent la performance

Erreurs de rendu (change detection)

Problèmes directement liés à la fréquence et à la portée de la détection des changements dans le DOM.

Fonctions dans les templates, stratégies de détection par défaut.

Erreurs d’architecture

Manque de séparation des préoccupations (SoC) et mauvaise gestion du cycle de vie des modules/composants.

Pour sortir la logique métier des composants, le pattern Strategy appliqué aux formulaires dynamiques est un bon exemple de découplage : le composant ne connaît plus aucune règle de validation.

Containers/Presentational, Lazy Loading, Structure des Directives.

Erreurs de gestion d’état

Mauvaise maîtrise des outils asynchrones et de la gestion de l’état global.

RxJS, Redux/Ngrx, gestion des Observables.

Les 10 pièges majeurs à éviter en Angular

1. Appeler des fonctions dans les templates

Des fonctions recalculées à chaque cycle de détection des changements perturbent la performance et introduisent une complexité inutile. Utilisez plutôt des Pipes Pures ou le pattern RxJS Push.

2. Des composants qui ne dépendent pas que de leurs inputs

Un composant devrait se comporter comme une fonction pure, ne dépendant que de ses @Input(). L’ajout de dépendances implicites via des services non réactifs compromet le Clean Code et crée des calculs superflus.

3. Confondre composants container et presentational

Ne pas distinguer les responsabilités (Container : gestion de l’état ; Présentation : affichage) entraîne un mélange des logiques, alourdit le code, et nuit à la maintenabilité.

4. Un NgRx mal maîtrisé

Une gestion de l’état global mal conçue (trop de sélecteurs, états trop imbriqués) ajoute une complexité technique inutile, rendant le code difficile à suivre et dégradant la performance des applications.

5. RxJS sous-exploité ou mal géré

RxJS est au cœur d’Angular. Le minimalisme ou l’oubli des opérateurs (comme distinctUntilChanged, switchMap) empêche un traitement asynchrone fluide et conduit à des fuites de mémoire (oublis de `unsubscribe`).

6. L’absence de lazy loading

Ne pas découper l’application en modules chargés à la demande alourdit le bundle initial, ce qui impacte directement la performance perçue par l’utilisateur et le temps de chargement initial (TTI).

7. Abuser des directives structurelles (*ngIf, *ngFor)

Mal gérées, ces directives peuvent provoquer des comportements imprévisibles dans le DOM. Attention particulière au `*ngFor` dans des listes massives qui nécessite l’usage de la fonction `trackBy` pour optimiser le rendu.

8. Laisser ChangeDetectionStrategy.Default partout

Laisser Angular scanner l’intégralité de l’arbre des composants pour des changements mineurs est une source majeure de perte de performance. L’adoption de `OnPush` est la solution pour les applications de grande taille.

9. Des directives personnalisées mal conçues

Les directives sont conçues pour encapsuler du comportement (DOM, événements). Si elles sont mal designées et contiennent trop de logique métier, elles deviennent des points de complexité qui brisent les principes du Clean Code.

10. Méconnaître les outils avancés

Des outils comme `ViewEncapsulation.None`, l’API `ChangeDetectorRef` (`detach`/`reattach`) ou la maîtrise de Zone.js sont rarement exploités à leur plein potentiel, laissant des marges d’optimisation importantes non explorées dans l’architecture.

Zoom technique : adopter la stratégie OnPush

Le passage de la stratégie de détection des changements à OnPush est le levier de performance le plus rapide à implémenter. Il dit à Angular de ne vérifier le composant et ses enfants que si :

  1. Un @Input() a été modifié (par référence).
  2. Un événement a été déclenché par le composant ou un de ses enfants.
  3. Vous avez explicitement demandé une vérification (`markForCheck()`).
// Dans votre composant TypeScript
import { ChangeDetectionStrategy } from '@angular/core';

@Component({
  selector: 'app-pure-component',
  templateUrl: './pure.component.html',
  // Active la stratégie OnPush
  changeDetection: ChangeDetectionStrategy.OnPush, 
})
export class PureComponent {
    // ...
}

Impact Clean Code : Cette stratégie force les développeurs à utiliser l’Immuabilité des données (ne pas modifier un objet, mais créer une nouvelle référence), ce qui rend le code plus prévisible et réduit drastiquement les cycles inutiles.

Conclusion : la performance est une décision d’architecture

La performance d’une application Angular repose autant sur le choix du framework que sur la discipline et la rigueur du code écrit. Ignorer les principes du Clean Code ou les mécanismes internes d’Angular mène inévitablement à un système coûteux à maintenir et lent à l’exécution.

Devenir un développeur senior en Angular signifie transformer ces « pièges » en opportunités d’architecture, en adoptant des patterns qui garantissent la scalabilité, comme l’Immuabilité, le Reactive Programming (RxJS) et le `ChangeDetectionStrategy.OnPush`.

Investir dans le Clean Code aujourd’hui, c’est garantir la performance et la stabilité de votre application Angular demain.

Pour aller plus loin

Une leçon, un kata, chaque mois

Les nouveaux articles et un exercice de refactoring, directement par e-mail.

S'inscrire à la newsletter