← Retour au blog
AngularNgRxState ManagementSignalsArchitecture

NgRx SignalStore vs Service à Signaux : quelle architecture choisir en 2026

NgRx SignalStore représente une rupture avec l'approche traditionnelle RxJS de NgRx. Là où les stores classiques reposent sur des observables et une architecture action-reducer-selector, SignalStore exploite les signaux d'Angular pour une réactivité plus directe et des changements de détection plus prévisibles. Parallèlement, une alternative plus légère émerge : un service métier qui expose simplement des signaux writable et computed, sans framework de gestion d'état. Le choix entre ces deux approches ne relève pas de la religion architecturale, mais de la complexité réelle de votre domaine métier et de vos contraintes de maintenabilité.

SignalStore : quand la structure paie vraiment

SignalStore propose une structure opinionée : des features avec état local et global, des effets déclaratifs, une sérialisation d'état prête à l'emploi. Cette ossature force une organisation cohérente, particulièrement utile dans les applications d'équipe ou les projets de plus de 50 000 lignes de code. Les signaux writable et computed de SignalStore permettent une dérivation d'état très granulaire. Si vous gérez un panier d'e-commerce avec calculs de TVA dynamiques, conversions de devises et états de synchronisation serveur, SignalStore impose un chemin clair : les effets gèrent les appels HTTP, les actions décrivent les intentions métier, les computed maintiennent des vues dérivées cohérentes. Cela élimine une catégorie entière de bugs liés aux incohérences temporelles entre plusieurs sources de vérité.

La courbe d'apprentissage reste raide. Les développeurs Angular habitués à RxJS trouvent les effets SignalStore contre-intuitifs au début : ils mélangent déclaratif et impératif, avec une logique de re-exécution basée sur les dépendances de signaux. Déboguer un effet qui se déclenche trop souvent ou pas au bon moment exige de comprendre le graphe de dépendances sous-jacent. Pour les migrations depuis un store NgRx classique, l'investissement est significatif, mais le gain en performance et en simplicité du change detection justifie l'effort dans les projets de taille moyenne à grande.

Le service à signaux : pragmatisme et légèreté

Un service métier simple avec signaux writable et computed offre une alternative convaincante pour 70 % des cas d'usage réels. Prenons un exemple concret : un service de liste de tâches. Au lieu de créer un store SignalStore, vous exposez un writable signal pour les tâches, un computed pour le compte de tâches complétées, et des méthodes qui mutent directement l'état. Cette approche élimine la boîterie de la gestion d'état : pas d'actions à dispatcher, pas d'effets à orchestrer, pas de sérialisation d'état à configurer. Le code est plus court, plus lisible pour les juniors, et les changements d'état sont immédiats et tracables avec un simple tap sur le signal.

Le service à signaux brille particulièrement dans les domaines à faible entropie : gestion d'UI locale (modal ouverte ou fermée, filtre appliqué), cache simple de données côté client, état de formulaire. Voici un exemple minimal :

export class TaskService {

private tasks = signal<Task[]>([]);

public tasks$ = this.tasks.asReadonly();

public completedCount = computed(() =>

this.tasks().filter(t => t.done).length

);

addTask(title: string) {

this.tasks.update(arr => [...arr, { id: nanoid(), title, done: false }]);

}

toggleTask(id: string) {

this.tasks.update(arr =>

arr.map(t => t.id === id ? { ...t, done: !t.done } : t)

);

}

}

Ce service tient dans une cinquantaine de lignes. Aucun boilerplate NgRx, aucune action créée, aucun effet déclaratif. Les composants consomment tasks$ et completedCount() directement via la OnPush detection. Pour la plupart des applications métier, c'est suffisant et plus maintenable qu'une infrastructure SignalStore surdimensionnée.

Les pièges réels et les cas limites

Le premier piège : confondre facilité initiale et scalabilité à long terme. Un service à signaux fonctionne parfaitement jusqu'au moment où vous devez synchroniser l'état entre plusieurs pages, implémenter un système de cache avec invalidation intelligente, ou ajouter de la persistence locale. À ce stade, l'absence de structure devient une dette technique. Vous vous retrouvez avec des services qui s'appellent entre eux, des patterns ad hoc d'invalidation de cache, et aucune trace claire du flux de données. SignalStore force une hygiène qui prévient ces situations.

Le deuxième piège : ignorer le coût de la dépendance NgRx. SignalStore ajoute environ 40 Ko gzippés à votre bundle. Si votre application tient en 200 Ko gzippés au total, cette dépendance pèse. Pour un petit dashboard interne ou une micro-frontend, le service à signaux reste plus léger. Mesurez votre bundle réel, pas vos hypothèses.

Un troisième piège, spécifique à SignalStore : les effets qui s'exécutent inopportunément. Si vous déclarez une dépendance sur un signal qui change fréquemment (comme une zone de recherche), votre effet peut se déclencher des dizaines de fois par seconde. Il faut apprendre à débouncer, à utiliser les pipeables comme tapResponse, et à maîtriser le lifecycle des effects pour éviter les fuites mémoire et les appels HTTP en cascade. Un développeur junior mal guidé peut créer un enfer de dépendances circulaires et de re-renders inutiles.

Critères de décision pratiques

Utilisez SignalStore si : vous gérez plus de trois domaines métier distincts, votre état dépend de plusieurs sources asynchrones (WebSocket, polling, événements utilisateur), vous avez besoin de time-travel debugging ou de persistence d'état, ou votre équipe compte plus de quatre développeurs travaillant sur la même feature. L'investissement initial est rapidement rentabilisé.

Restez avec un service à signaux si : votre application est principalement locale (peu ou pas d'appels HTTP asynchrones), l'état métier est simple et peu dépendant d'autres états, vous travaillez seul ou en très petit groupe, ou vous avez des contraintes strictes de bundle size. Le pragmatisme paie ici.

Une approche hybride existe aussi : utilisez SignalStore pour le domaine métier critique (panier, authentification, données partagées), et des services à signaux pour l'UI locale (modaux, filtres, pagination). Cela combine la rigueur architecturale là où elle compte vraiment et la légèreté où c'est possible.

Conclusion : choisir selon le contexte, pas la tendance

En 2026, NgRx SignalStore n'est plus un choix idéologique, mais pragmatique. Il résout des problèmes réels de cohérence et de performance dans les applications complexes. Cependant, il ne remplace pas un service à signaux bien conçu pour 70 % des cas d'usage courants. Commencez par évaluer honnêtement la complexité de votre domaine métier : avez-vous vraiment besoin d'une action pour chaque intention utilisateur ? Votre état dépend-il de multiples sources asynchrones imbriquées ? Si les réponses sont non, un service à signaux suffit et vous économisez de la maintenance. Si oui, SignalStore devient un investissement judicieux. Mesurez votre bundle, testez les deux approches sur une feature non-critique, et décidez en connaissance de cause. C'est ça, l'architecture pragmatique.

Développeur Angular & Mobile freelance — Strasbourg.

© 2026 Emilien Pons — Tous droits réservés.Conçu avec Angular, PrimeNG et ❤️