AngularJS vs Angular : comparaison complète

Front-end 06/04/2026 22:00:00 Mezgani said
Angularjs Angular Comparaison Migration Architecture
AngularJS vs Angular : comparaison complète

AngularJS 1.x vs Angular 21 : architecture, performance, DI, routing, RxJS, Signals — comparaison technique pour choisir ou migrer.

Histoire et contexte

AngularJS (version 1.x) a été créé par Google en 2010 et a révolutionné le développement web en popularisant le two-way data binding et le MVC côté client. Pendant des années, il a dominé l'écosystème frontend.

En 2016, Google publie Angular 2 — une réécriture complète en TypeScript, incompatible avec AngularJS. La confusion des noms persiste encore aujourd'hui : "AngularJS" désigne la version 1.x, "Angular" (sans JS) désigne les versions 2 et supérieures (v21 en 2026).

AngularJS a atteint sa fin de vie officielle le 31 décembre 2021. Les applications AngularJS encore en production ne reçoivent plus de correctifs de sécurité.

En chiffres (2026) : Angular est utilisé par plus de 3 millions de développeurs. AngularJS compte encore des millions de lignes de code en production dans des systèmes legacy — c'est pourquoi comprendre les deux reste stratégique.

Architecture : MVC vs Composants

La différence architecturale la plus profonde est le paradigme de construction de l'UI : AngularJS suit le pattern MVC avec des controllers et des scopes, Angular adopte entièrement l'architecture par composants.

AngularJS : Model-View-Controller

// Controller AngularJS : logique dans un objet $scope
angular.module('app')
  .controller('ProductCtrl', function($scope, ProductService) {
    $scope.products = [];       // modèle
    $scope.filter = '';         // état UI

    // Charge les produits au démarrage
    ProductService.getAll().then(function(data) {
      $scope.products = data;
    });

    // Filtre les produits par nom
    $scope.filtered = function() {
      return $scope.products.filter(function(p) {
        return p.name.includes($scope.filter);
      });
    };
  });

Angular 21 : Architecture composants

// Composant Angular : logique encapsulée avec Signals
@Component({
  selector: 'app-products',
  standalone: true,
  imports: [FormsModule],
  template: `
    <input [(ngModel)]="filter" />
    @for (p of filtered(); track p.id) {
      <div>{{ p.name }}</div>
    }
  `,
})
export class ProductsComponent {
  private svc = inject(ProductService);
  products = signal<Product[]>([]);
  filter = signal('');

  // computed() recalcule uniquement quand products() ou filter() change
  filtered = computed(() =>
    this.products().filter(p => p.name.includes(this.filter()))
  );

  ngOnInit() {
    this.svc.getAll().subscribe(data => this.products.set(data));
  }
}
AspectAngularJSAngular 21
ParadigmeMVC + $scopeComposants + Signals
Unité de baseController + TemplateComposant autonome
État$scope (mutable)signal() (réactif)
LangageJavaScript ES5TypeScript strict
Modulesangular.module()NgModules / standalone

Change detection : $digest vs Signals

Le mécanisme de détection des changements est la différence de performance la plus significative entre les deux frameworks.

AngularJS : le cycle $digest (dirty checking)

// AngularJS parcourt TOUS les watchers à chaque cycle
// Un simple clic peut déclencher des centaines de vérifications

angular.module('app')
  .controller('PerfCtrl', function($scope) {
    // Chaque $watch enregistre une expression à surveiller
    $scope.$watch('user.name', function(newVal, oldVal) {
      // Déclenché quand user.name change
      console.log('Changement détecté:', newVal);
    });

    // $apply force un nouveau cycle $digest manuellement
    // (nécessaire quand on modifie le scope hors d'Angular)
    setTimeout(function() {
      $scope.$apply(function() {
        $scope.user.name = 'Alice'; // sans $apply, l'UI ne se met pas à jour
      });
    }, 1000);
  });

// Problème de performance : avec 2000 watchers,
// chaque interaction déclenche 2000 vérifications
// C'est le "2000 watchers problem" bien documenté

Angular 21 : Signals (réactif, précis)

// Angular Signals : seuls les composants dépendants de ce signal
// sont re-rendus — zéro dirty checking

@Component({ standalone: true, template: `{{ userName() }}` })
export class UserComponent {
  // signal() crée une valeur réactive
  userName = signal('Bob');

  // computed() dépend automatiquement de userName
  userLabel = computed(() => 'Utilisateur : ' + this.userName());

  // effect() réagit aux changements sans $watch manuel
  logEffect = effect(() => {
    console.log('Nom mis à jour :', this.userName());
    // Déclenché uniquement quand userName() change
  });

  updateName(name: string) {
    this.userName.set(name); // Angular sait exactement quoi re-rendre
  }
}
Gain de performance : Signals + mode zoneless éliminent entièrement zone.js (~14KB gzip) et rendent le re-rendu jusqu'à 10× plus précis qu'AngularJS sur des listes de données importantes.

Injection de dépendances

AngularJS : tokens sous forme de chaînes

// AngularJS : DI basé sur les noms de paramètres (fragile en minification)
angular.module('app')
  .controller('OrderCtrl', function($scope, OrderService, UserService) {
    // Les noms '$scope', 'OrderService', 'UserService' sont des tokens
    // PROBLÈME : la minification renomme les paramètres → DI cassée !
  });

// Solution : annotation explicite $inject
angular.module('app')
  .controller('OrderCtrl', ['$scope', 'OrderService', 'UserService',
    function($scope, OrderService, UserService) {
      // Maintenant la minification ne casse plus rien
    }
  ]);

Angular 21 : DI basée sur les types TypeScript

// Angular : DI via types — robuste, compile-time safe
@Component({ standalone: true })
export class OrderComponent {
  // inject() — pattern moderne (Angular 14+)
  private orderService = inject(OrderService);
  private userService = inject(UserService);

  // Ou via constructeur (pattern classique toujours valide)
  constructor(
    private http: HttpClient,
    private router: Router,
  ) {}
}

Templates et routing

Templates : directives vs syntaxe native

FonctionnalitéAngularJSAngular 21
Conditionng-if="expr"@if (expr) { }
Boucleng-repeat="x in list"@for (x of list; track x.id) { }
Switchng-switch@switch (val) { @case (x) { } }
Liaison valeurng-model="x"[(ngModel)]="x"
Événement clicng-click="fn()"(click)="fn()"
Interpolation{{ expr }}{{ expr }}
Classe conditionnelleng-class="{active: x}"[class.active]="x"
Chargement différé❌ (manuel)@defer { } @loading { }

Routing comparé

// AngularJS : ngRoute
angular.module('app', ['ngRoute'])
  .config(function($routeProvider) {
    $routeProvider
      .when('/users', { templateUrl: 'users.html', controller: 'UserCtrl' })
      .when('/users/:id', { templateUrl: 'user.html', controller: 'UserDetailCtrl' })
      .otherwise({ redirectTo: '/' });
  });
// Angular 21 : Router standalone avec lazy loading
export const routes: Routes = [
  { path: 'users', component: UserListComponent },
  { path: 'users/:id', component: UserDetailComponent },
  {
    path: 'admin',
    // Lazy loading : le module admin est chargé à la demande
    loadChildren: () => import('./admin/routes').then(m => m.adminRoutes),
    canActivate: [authGuard],
  },
  { path: '', redirectTo: 'users', pathMatch: 'full' },
];

Performance et bundle size

MétriqueAngularJS 1.xAngular 21 (standalone)
Bundle minimal (gzip)~55KB~45KB
Re-rendu 1000 lignes~80ms (dirty check)~8ms (Signals)
SSR / Hydration✅ (hydration incrémentale)
Tree-shaking❌ (tout ou rien)✅ (standalone complet)
Lazy loadingPartiel (ui-router)✅ natif (Router)
Web WorkersDifficile✅ (Angular CDK)
Lighthouse Score~60-70~95-100 (optimisé)

Écosystème et tooling

OutilAngularJSAngular 21
CLIGrunt/Gulp (manuel)Angular CLI (ng)
BundlerWebpack (manuel)esbuild + Vite (natif)
Tests unitairesKarma + JasmineVitest / Jest
Tests e2eProtractor (EOL)Playwright / Cypress
State management$scope, $rootScopeSignals, NgRx Signal Store
UI ComponentsUI Bootstrap (archivé)Angular Material 3 (MDC)
DevToolsBatarang (obsolète)Angular DevTools v2 (Chrome)
Mises à jour sécurité❌ (EOL 2021)✅ (active)

Quand choisir quoi ?

Utiliser AngularJS si…

  • Vous maintenez une application legacy qui ne peut pas être migrée immédiatement
  • Le budget ou le temps de migration n'est pas disponible dans l'immédiat
  • L'application est en fin de vie et sera remplacée par un nouveau projet

Utiliser Angular 21 si…

  • Vous démarrez un nouveau projet frontend en 2026
  • Vous avez besoin de SSR, d'hydration ou de performances Lighthouse élevées
  • Votre équipe utilise TypeScript et veut un framework opinionné et maintenu
  • Vous avez besoin de support à long terme et de mises à jour de sécurité
  • Vous construisez une application enterprise scalable
Verdict : Pour tout nouveau projet, Angular 21 est le seul choix raisonnable. Pour les projets existants AngularJS, planifiez la migration dès maintenant — chaque mois sans migration est un risque de sécurité et une dette technique croissante.

Partager