// 01 · le-contexte
Le contexte
Une application critique d'administration interne d'un grand groupe énergétique français, utilisée quotidiennement par des administrateurs systèmes pour gérer leur infrastructure.
Côté tech : une codebase Angular 16 vieillissante, héritée de migrations partielles, avec des bad practices accumulées (composants monolithiques, services overloadés, typage faible, gestion d'état incohérente). Côté backend, du Java avec des problèmes de performance identifiés sur certains traitements (requêtes mal optimisées, boucles imbriquées).
L'enjeu de la mission : moderniser l'IHM pour bénéficier des dernières features Angular (Signals, Standalone Components, nouveaux control flows), renforcer la sécurité des endpoints, et poser des fondations propres pour les évolutions futures du produit.
// 02 · la-solution
La solution
Le projet majeur sur lequel j'ai travaillé en autonomie : la refonte from scratch de l'IHM Angular.
Le choix structurant : nouveau repo plutôt que migration in-place
Le cas classique pour migrer Angular 16 → 21, c'est de monter version par version dans le repo existant. C'est long, ça traîne les bad practices héritées, et ça monopolise une grosse partie du temps de dev pour un gain limité.
J'ai fait un autre choix : créer un nouveau repo Angular 21 from scratch, repartir sur des bases saines, et y porter progressivement les fonctionnalités. La logique : le temps qu'aurait pris la migration in-place ne valait pas le résultat. Mieux valait investir le même budget dans une codebase moderne, scalable, et maintenable sur le long terme.
Concrètement, sur le nouveau repo :
- →Standalone Components partout (suppression des NgModules)
- →Signals pour la gestion d'état réactive
- →Nouveaux control flows (
@if,@for,@switch) - →TypeScript strict (suppression de tous les
any) - →Architecture composants modulaire et réutilisable
// Pattern type sur le nouveau repo
@Component({
selector: "app-import-list",
standalone: true,
imports: [ImportRowComponent],
template: `
@for (imp of imports(); track imp.id) {
<app-import-row [import]="imp" />
} @empty {
<app-empty-state />
}
`,
})
export class ImportListComponent {
private service = inject(ImportService);
imports = toSignal(this.service.getImports(), { initialValue: [] });
}
Refonte sécuritaire de 150+ endpoints (GET → POST)
L'application avait plus de 150 endpoints GET qui passaient des données sensibles en query string — visibles dans les logs serveur, dans les historiques navigateur, et exposées aux outils de monitoring tiers.
J'ai mené la migration complète de ces endpoints vers POST, avec les payloads en body. Au passage, j'ai aussi :
- →Amélioré certaines requêtes côté serveur (filtrage des données utiles uniquement, pagination)
- →Mis en place Swagger / OpenAPI pour que la documentation API soit synchronisée avec le code et à jour automatiquement
C'était plus qu'un simple rename de verbe HTTP : c'était l'occasion d'auditer la sécurité de chaque endpoint, de corriger les vulnérabilités détectées par Checkmarx et SonarQube, et de rationaliser les contrats d'API.
Apport sur l'optimisation backend
J'ai également contribué (sans en être le porteur principal) à l'identification de bottlenecks backend : requêtes mal optimisées, boucles imbriquées, traitements Java qui pouvaient être réécrits proprement. Les optimisations ont été menées en collaboration avec l'équipe back.
// 03 · les-dfis-techniques
Les défis techniques
Convaincre de l'approche "nouveau repo". Ce n'est jamais la décision par défaut sur une mission ESN — la culture est plutôt à la migration in-place. J'ai porté l'argumentaire : temps de dev équivalent, codebase finale 10x plus saine, possibilité de poser de vraies fondations scalables, moins de dette technique reportée.
Garantir la cohérence pendant la cohabitation. Pendant la transition, l'ancienne app continuait à tourner en parallèle. Les nouvelles fonctionnalités devaient s'intégrer aux mêmes APIs backend, avec les mêmes contrats. J'ai documenté précisément les correspondances pour qu'il n'y ait pas de dérive entre les deux mondes.
150+ endpoints à migrer sans casser la prod. Chaque endpoint GET → POST = un changement potentiel de comportement côté client et serveur. Tests automatisés systématiques, livraison progressive, monitoring Grafana en temps réel pour détecter les anomalies dès les premières minutes.
// 04 · rsultats
Résultats
- →Codebase Angular 21 from scratch : Standalone Components, Signals, control flows, TypeScript strict
- →Plus de 150 endpoints migrés de GET vers POST avec sécurisation des payloads
- →Documentation Swagger mise en place et synchronisée avec le code
- →Fondations posées pour la scalabilité future du produit
- →Vulnérabilités identifiées par Checkmarx et SonarQube corrigées au passage
// 05 · stack-technique
Stack technique
| Layer | Technos |
|---|---|
| Frontend | Angular 21, RxJS, TypeScript strict, Standalone Components, Signals |
| Backend | Java 21, Spring Boot (collaboration avec l'équipe back) |
| Doc API | Swagger / OpenAPI |
| Sécurité & qualité | Checkmarx, SonarQube, revues de code systématiques |
| CI/CD | GitLab CI, Jenkins |
| Monitoring | Grafana (dashboards dédiés) |
// 06 · ce-que-je-retiens
Ce que je retiens
Cette mission m'a appris à arbitrer entre la solution facile et la solution juste. Migrer Angular 16 → 21 in-place aurait été le réflexe par défaut. Partir d'un nouveau repo était plus structurant, plus risqué côté communication interne — mais le résultat est une codebase qui tiendra 5 ans sans avoir besoin d'être réécrite.
C'est aussi cette expérience qui m'a donné le goût des refontes propres comme axe de mission freelance aujourd'hui : quand on hérite d'un code qui ralentit l'équipe, parfois la meilleure réponse n'est pas "on optimise", c'est "on repart sur des bases saines, en transférant ce qui mérite de l'être".