AngularJS hace tiempo que llegó al final de su vida útil: no hay parches de seguridad, no hay actualizaciones de dependencias y un grupo cada vez menor de desarrolladores que lo conocen. Continuar manteniendo una aplicación AngularJS en producción significa acumular riesgo de seguridad, deuda técnica y costo de contratación. Esta guía cubre todo el viaje hacia Angular moderno: auditoría de código heredado, elección entre migración de patrones big bang y estrangulador incremental, arranque híbrido con ngUpgrade, mapeo conceptual directo (controlador, directiva, $http, enrutamiento, autenticación), pruebas, rendimiento y un plan operativo de 30/60/90 días con KPI mensurables.
Por qué migrar de AngularJS a Angular
El salto de AngularJS a Angular no es una simple actualización de versión: es un cambio de paradigma, de un marco basado en un omnipresente enlace de datos bidireccional y $scope a un modelo de components con inyección de dependencia escrita, detección optimizada de cambios y compilación AOT. Los beneficios son mensurables (paquetes más pequeños gracias a TypeScript de extremo a extremo, un ecosistema que se mantiene activamente) pero deben sopesarse con el riesgo real de una migración mal planificada: regresiones funcionales, equipo estancado durante meses, lanzamientos de funciones congelados.
Beneficios y riesgos de un vistazo
| Beneficios de la migración | Riesgos a gestionar |
|---|---|
| Rendimiento superior (detección de cambios, AOT, agitación de árboles) | Regresiones funcionales en características heredadas no probadas |
| TypeScript de extremo a extremo, menos errores en tiempo de ejecución | Alto costo inicial sin liberación inmediata de valor |
| Ecosistema mantenido, seguridad actualizada | Equipo aprendiendo nuevo paradigma bajo presión |
| Más fácil de encontrar desarrolladores en el mercado | Código híbrido temporal más complejo de depurar |
Evaluación inicial: auditoría de código AngularJS
Antes de escribir una línea de Angular, debes trazar con precisión lo que estás migrando. Una auditoría superficial es la causa más común de malas estimaciones y de migraciones que se estancan a medio camino. La auditoría debe responder tres preguntas: qué tan grande es el código, qué tan internamente está acoplado y qué dependencias externas están involucradas.
Lista de verificación de auditoría operativa
- Inventario de módulos: enumera cada módulo de AngularJS (
angular.module(...)) y sus dependencias declaradas. - Recuento de controlador/directiva/servicio: Utilice
grep -rn "\.controller(\|\.directive(\|\.factory(\|\.service(" src/) para un recuento rápido y objetivo. - Mapa de $scopes compartidos: identifique el uso de
$rootScopepor estado global; casi siempre es el punto ideal para migrar a servicios Angular. - Dependencias específicas de AngularJS:
angular-ui-router,angular-translate,restangularno tienen equivalente directo y deben ser reemplazado, no traducido línea por línea. - Cobertura de prueba existente: Sin pruebas, cada refactorización es un salto en la oscuridad; Mida la cobertura actual antes de comenzar.
- Clasificación por criticidad: dividir las características en "negocio principal" (alto riesgo, migrar último, con más pruebas) y "periféricas" (buen punto de partida).
Estrategia de migración: big bang versus incremental (patrón estrangulador)
Hay dos enfoques principales. El big bang reescribe toda la aplicación en Angular antes de lanzar cualquier cosa: arriesgado en aplicaciones grandes, pero más fácil de razonar en proyectos pequeños. El estrangulador (incremental) permite que AngularJS y Angular coexistan en la misma aplicación a través de ngUpgrade, migrando una característica a la vez y lanzando continuamente: más lento en el corto plazo, pero reduce drásticamente el riesgo y permite que la empresa continúe recibiendo valor durante la migración.
Cómo elegir el enfoque correcto
| Criterio | Big bang | Patrón estrangulador (incremental) |
|---|---|---|
| Tamaño de la aplicación | Pequeña/mediana (< 50 componentes) | Grande, empresarial |
| Tolerancia al riesgo empresarial | Alta (la liberación se puede bloquear) | Baja (se requiere continuidad) |
| Equipo disponible | Dedicado a tiempo completo a la migración | Dividido entre nuevas funciones y migración |
| Cobertura de prueba existente | No crítico | Muy recomendado |
Para la mayoría de las aplicaciones empresariales del mundo real, el patrón estrangulador es la elección correcta: le permite validar cada módulo migrado a producción antes de continuar con el siguiente.
Configuración del entorno de desarrollo
Antes de iniciar la refactorización, necesita las herramientas adecuadas instaladas y configuradas correctamente, incluido el paquete @angular/upgrade que permite la interoperabilidad entre los dos marcos.
Lista de verificación de herramientas necesarias
# Verifica versioni installate
node -v # Node 20.x LTS o superiore
npm -v
# Installa Angular CLI globalmente
npm install -g @angular/cli
# Crea il progetto Angular che ospiterà il bootstrap ibrido
ng new my-app --routing --style=scss
cd my-app
# Installa il modulo di interoperabilità con AngularJS
npm install @angular/upgrade
# Installa AngularJS stesso come dipendenza (per il periodo ibrido)
npm install angular@1.8.3
Refactor y mapeo conceptual: de AngularJS a Angular
La parte más delicada de la migración es traducir correctamente los conceptos arquitectónicos. Cada construcción de AngularJS tiene un equivalente de Angular conceptualmente cercano, pero con una semántica y un ciclo de vida diferentes.
Tabla de mapeo conceptual
| AngularJS | Angular moderno |
|---|---|
$scope | Propiedades de clase de componente (this) |
$rootScope para el estado global | Service @Injectable({ provideIn: 'root' }) con BehaviorSubject o señal |
.controller() | Clase de componente con @Component() |
.directive() | Componente o Directiva (@Directive()) dependiendo de si tiene plantilla |
.factory() / .service() | Clase con @Injectable(), inyectado vía constructor |
$http | HttpClient (RxJS observable en lugar de promesa) |
$route / ui-router | RouterModule con ruta independiente o cargado de forma diferida |
Encuadernación =, @, & | @Input(), @Output() con Emisor de eventos |
Fragmento 1–2: Controlador → Componente
// AngularJS — controller
angular.module('app').controller('UserListController', function($scope, UserService) {
$scope.users = [];
$scope.loading = false;
$scope.loadUsers = function() {
$scope.loading = true;
UserService.getAll().then(function(res) {
$scope.users = res.data;
$scope.loading = false;
});
};
$scope.loadUsers();
});
// Angular — component equivalente
@Component({
selector: 'app-user-list',
standalone: true,
templateUrl: './user-list.component.html',
})
export class UserListComponent implements OnInit {
users: User[] = [];
loading = false;
constructor(private userService: UserService) {}
ngOnInit(): void {
this.loadUsers();
}
loadUsers(): void {
this.loading = true;
this.userService.getAll().subscribe((users) => {
this.users = users;
this.loading = false;
});
}
}
Fragmento 3–4: Directiva compleja → Componente
// AngularJS — directive con isolate scope
angular.module('app').directive('userCard', function() {
return {
restrict: 'E',
scope: { user: '=', onSelect: '&' },
template: '<div class="card" ng-click="onSelect({user: user})">{{user.name}}</div>',
};
});
// Angular — component con Input/Output
@Component({
selector: 'app-user-card',
standalone: true,
template: `<div class="card" (click)="select.emit(user)">{{ user.name }}</div>`,
})
export class UserCardComponent {
@Input({ required: true }) user!: User;
@Output() select = new EventEmitter<User>();
}
Fragmento 5–6: Servicio AngularJS → Servicio Angular con DI
// AngularJS — factory
angular.module('app').factory('UserService', function($http) {
return {
getAll: function() {
return $http.get('/api/users');
},
};
});
// Angular — servizio con HttpClient e DI
@Injectable({ providedIn: 'root' })
export class UserService {
constructor(private http: HttpClient) {}
getAll(): Observable<User[]> {
return this.http.get<User[]>('/api/users');
}
}
Fragmento 7–8: enrutamiento y llamadas HTTP
// AngularJS — ui-router
$stateProvider.state('users.detail', {
url: '/users/:id',
template: '<user-detail user-id="$resolve.userId"></user-detail>',
resolve: {
userId: ['$stateParams', function($stateParams) { return $stateParams.id; }],
},
});
// Angular — Router standalone con lazy loading
export const routes: Routes = [
{
path: 'users/:id',
loadComponent: () =>
import('./user-detail/user-detail.component').then((m) => m.UserDetailComponent),
},
];
// Nel component: lettura del parametro via ActivatedRoute
export class UserDetailComponent implements OnInit {
userId = signal<string | null>(null);
constructor(private route: ActivatedRoute) {}
ngOnInit(): void {
this.userId.set(this.route.snapshot.paramMap.get('id'));
}
}
Autenticación y gestión de estado
Es necesario repensar el flujo de autenticación, no sólo traducirlo. En AngularJS es común manejar el token en $rootScope con un interceptor en $http; en Angular el patrón correcto es un AuthService centralizado con estado reactivo (BehaviorSubject o señal) y un HttpInterceptorFn.
Migración del flujo de autenticación
// auth.service.ts
@Injectable({ providedIn: 'root' })
export class AuthService {
private tokenSignal = signal<string | null>(localStorage.getItem('access_token'));
readonly isAuthenticated = computed(() => !!this.tokenSignal());
constructor(private http: HttpClient) {}
login(credentials: LoginPayload): Observable<AuthTokens> {
return this.http.post<AuthTokens>('/api/auth/login', credentials).pipe(
tap((tokens) => this.setTokens(tokens)),
);
}
refresh(): Observable<AuthTokens> {
return this.http.post<AuthTokens>('/api/auth/refresh', {}).pipe(
tap((tokens) => this.setTokens(tokens)),
);
}
private setTokens(tokens: AuthTokens): void {
localStorage.setItem('access_token', tokens.accessToken);
this.tokenSignal.set(tokens.accessToken);
}
}
// auth.interceptor.ts — funzione, non più basata su $http config
export const authInterceptor: HttpInterceptorFn = (req, next) => {
const token = localStorage.getItem('access_token');
const cloned = token ? req.clone({ setHeaders: { Authorization: `Bearer ${token}` } }) : req;
return next(cloned);
};
Para una gestión de estado más amplia (no solo autenticación), en aplicaciones empresariales complejas es mejor evaluar NgRx, que ofrece un almacén centralizado predecible; Sin embargo, en la mayoría de los casos, los servicios con BehaviorSubject o señal son suficientes y mucho más fáciles de mantener que introducir un patrón completo similar a Redux.
Integración progresiva con ngUpgrade
ngUpgrade es el paquete oficial que permite que AngularJS y una aplicación Angular se ejecuten en la misma página, al mismo tiempo, compartiendo servicios y comunicándose entre componentes. Es el corazón técnico del patrón estrangulador.
Arranque híbrido: ejemplo práctico
// main.ts — bootstrap ibrido con downgradeModule
import { setUpLocationSync } from '@angular/upgrade/static';
import { UpgradeModule } from '@angular/upgrade/static';
@NgModule({
imports: [BrowserModule, UpgradeModule, AppRoutingModule],
declarations: [UserCardComponent],
})
export class AppModule {
constructor(private upgrade: UpgradeModule) {}
ngDoBootstrap(): void {
this.upgrade.bootstrap(document.body, ['legacyApp']);
setUpLocationSync(this.upgrade);
}
}
// Espone il component Angular come directive AngularJS,
// utilizzabile nei template AngularJS esistenti senza riscriverli
angular
.module('legacyApp')
.directive('appUserCard', downgradeComponent({ component: UserCardComponent }));
// Espone un servizio AngularJS ad Angular, per riuso durante la transizione
angular.module('legacyApp').factory('legacyUserService', downgradeInjectable(UserService));
Con esta configuración, una plantilla de AngularJS existente puede usar sin modificaciones, mientras que los nuevos componentes de Angular pueden inyectar servicios AngularJS heredados a través de upgradeInjectable, hasta que también se migren.
Pruebas durante la migración
El código híbrido es por naturaleza más frágil de probar: dos marcos, dos ciclos de resumen/detección de cambios, dos ejecutores de prueba diferentes coexisten durante meses. La estrategia correcta es mantener Karma/Jasmine en el código AngularJS que aún no se ha migrado, introducir Jest para cada nuevo componente de Angular (modo de vigilancia mejor y más rápido) y reemplazar gradualmente Protractor con (obsoleto) Cypress para E2E, que no depende del marco subyacente y prueba la aplicación tal como la ve el usuario.
Prueba de lista de verificación
- No elimine las pruebas de AngularJS existentes hasta que el módulo correspondiente se haya migrado por completo.
- Cada nuevo componente de Angular requiere pruebas unitarias antes está vinculado a través de
ngUpgrade, no después. - Cypress E2E debe cubrir los flujos críticos de un extremo a otro, atravesando AngularJS y páginas Angular durante el período híbrido.
- Supervise la cobertura general en cada sprint: nunca debe caer por debajo del nivel previo a la migración.
Optimización de rendimiento y paquetes
Durante el período híbrido, el paquete crece inevitablemente, porque contiene tanto AngularJS como Angular. Es fundamental monitorear este crecimiento y planear eliminar AngularJS tan pronto como se migre el último módulo.
Lista de verificación de desempeño
- Carga diferida agresiva en cada ruta Angular con
loadComponent/loadChildren, para no cargar todo el código nuevo antes de tiempo. - Compilación AOT siempre activo en producción (
ng buildlo usa de forma predeterminada desde la CLI moderna). - Analizador de paquetes se ejecuta en cada hito de migración, para verificar que AngularJS realmente se elimina al final del viaje y no permanece "muerto" en el paquete.
- Carga diferencial: Angular CLI genera automáticamente paquetes diferenciados para navegadores modernos/heredados cuando es necesario.
- Elimine
angular(1.x) depackage.jsony de cada importación tan pronto como se haya migrado el último módulo de AngularJS; este es el paso que se olvida con más frecuencia.
Implementación, CI/CD y estrategia de reversión
Cada módulo migrado debe publicarse detrás de un indicador de característica, para poder regresar instantáneamente a la versión de AngularJS en caso de una regresión crítica, sin una reversión completa de la implementación.
Marcas de funciones y reversión: ejemplo
// Semplice feature flag basato su configurazione remota
if (this.featureFlags.isEnabled('new-user-list-angular')) {
this.router.navigate(['/users']); // route Angular
} else {
window.location.href = '/legacy/users'; // route AngularJS esistente
}
La canalización de CI/CD debe realizar, para cada solicitud de extracción: compilación de producción, suite Jest/Karma, suite Cypress en flujos críticos y una verificación automática del tamaño del paquete con umbral máximo; un aumento anormal del paquete es a menudo el primer signo de una dependencia olvidada de AngularJS.
5 miniguías prácticas listas para publicar
Mini-guía 1 — Convertir un controlador AngularJS en un componente Angular
H1: Del controlador AngularJS al componente Angular: guía paso a paso
Introducción: El controlador es el primer bloque que migra en cada módulo: la conversión en componente siempre sigue el mismo patrón repetible.
Snippet (40-60 palabras): Un controlador AngularJS con $scope se convierte en una clase de componente Angular: las propiedades en $scope se convierten en propiedades de la clase, los métodos siguen siendo métodos y la inicialización que ocurrió en el controlador final se mueve a ngOnInit(). Las dependencias inyectadas mediante parámetros de función se convierten en parámetros de constructor escritos.
Estructura: H2 "Identificar el alcance del controlador" → H3 "Enumerar propiedades y métodos"; H2 "Crear clase de componente" → H3 "Mover lógica de inicialización"; H2 "Actualizar la plantilla".
Preguntas frecuentes breves: "¿Necesita migrar la plantilla junto con el controlador?" → "Sí, siempre juntos: cambios de sintaxis vinculante (ng-click → (click))." · "¿Puedo dejar $scope temporalmente?" → "No, no existe en Angular: debe eliminarse contextualmente."
Miniguía 2: Migrar una directiva compleja a un componente Angular
H1: Migrar una directiva AngularJS con alcance aislado al componente Angular
Introducción: Las directivas con alcance aislado y vinculantes =/@/& son el caso más común y se asignan casi 1:1 en Entrada/Salida.
Snippet (40-60 palabras): Un enlace = (bidireccional) se convierte en un @Input() combinado, si es necesario, con @Output() para notificar a los padres; un enlace (función) & se convierte directamente en un @Output() con EventEmitter. La template en línea de la directiva se convierte en la template/templateUrl del nuevo componente Angular.
Estructura: H2 "Analizar enlaces de directivas" → H3 "Asignar =, @, & a entrada/salida"; H2 "Crear componente" → H3 "Restricción de manejo: 'E' vs 'A'"; H2 "Actualizar usos en plantillas".
Preguntas frecuentes breves: "¿Qué sucede con la restricción: 'A' (directiva de atributo)?" → "Conviértete en @Directive() Angular sin plantilla". · "¿Aún se admiten enlaces bidireccionales?" → "Sí, mediante convención [(valor)] con Entrada+Salida acoplada."
Miniguía 3: Integración de ngUpgrade para un arranque híbrido
H1: AngularJS + Bootstrap híbrido angular con ngUpgrade
Introducción: El arranque híbrido es el paso habilitante para toda la estrategia incremental: sin él, cada migración es un big bang forzado.
Snippet (40-60 palabras): UpgradeModule.bootstrap() inicia ambos marcos en la misma página; downgradeComponent hace que un componente Angular se pueda utilizar en plantillas de AngularJS, upgradeComponent hace lo contrario. downgradeInjectable/upgradeInjectable comparten servicios entre los dos mundos, permitiendo la reutilización inmediata sin duplicar la lógica.
Estructura: H2 "Instalar @angular/actualizar" → H3 "Configurar ngDoBootstrap"; H2 "Exponer componentes Angular a AngularJS" → H3 "downgradeComponent en la práctica"; H2 "Compartir servicios entre los dos frameworks".
Preguntas frecuentes breves: "¿ngUpgrade está ralentizando la aplicación?" → "Un poco, para la detección de doble cambio: es un costo temporal, no permanente". · "¿Cuánto tiempo puede durar la fase híbrida?" → "Desde algunas semanas hasta muchos meses, dependiendo del tamaño de la aplicación."
Mini-guía 4 — Migrar enrutamiento desde ui-router a Angular Router
H1: De ui-router a Angular Router: Guía de migración de enrutamiento
Introducción: El enrutamiento es a menudo la última parte que se migra, porque afecta toda la estructura de navegación de la aplicación.
Snippet (40-60 palabras): Cada state de ui-router se convierte en una Route Angular: url se convierte path, template/controller se convierten en component (o loadComponent para carga diferida), y el resolve se convierte en resolve Angular basado en servicio con Resolve o simplemente lee el componente a través de ActivatedRoute.
Estructura: H2 "Mapa de estados existentes" → H3 "url → ruta, resolver → Resolver"; H2 "Configurar rutas con carga diferida" → H3 "loadComponent vs loadChildren"; H2 "Gestionar la coexistencia con setUpLocationSync".
Preguntas frecuentes breves: "¿Pueden coexistir los dos enrutadores?" → "Sí, temporalmente, con setUpLocationSync para sincronizar la URL". · "¿Qué uso en lugar de estados anidados de ui-router?" → "Rutas angulares anidadas con rutas secundarias y ."
Miniguía 5: Implementar la autenticación JWT y actualizar el token durante la migración
H1: Autenticación JWT con token de actualización durante la migración de AngularJS → Angular
Introducción: El flujo de autenticación debe funcionar de manera idéntica tanto en páginas AngularJS como en páginas que ya son Angulares, compartiendo el mismo token.
Snippet (40-60 palabras): Centraliza el token en localStorage (o cookie httpOnly, preferible por seguridad), leído tanto por el interceptor $http AngularJS como desde HttpInterceptorFn Angular. Un AuthService Angular expuesto a AngularJS a través de downgradeInjectable evita duplicar la lógica de inicio de sesión/actualización en los dos marcos durante el período híbrido.
Estructura: H2 "Centralizar la gestión de tokens" → H3 "Almacenamiento local frente a cookies httpOnly"; H2 "Compartir AuthService entre los dos marcos" → H3 "rebajarInjectable en la práctica"; H2 "Administrar actualización automática en 401".
Preguntas frecuentes breves: "¿Necesito duplicar el inicio de sesión en ambos marcos?" → "No, un único Angular AuthService compartido a través de downgradeInjectable es suficiente". · "¿Cómo manejo el cierre de sesión con un token vencido?" → "Intercepta 401 en ambos interceptores y redirige al inicio de sesión centralizado".
Estudio de caso: Migración de una aplicación empresarial
Un caso típico: aplicación de gestión AngularJS con 340 controladores, 85 directivas personalizadas y 6 años de desarrollo incremental. Con un enfoque de patrón estrangulador en equipos de 4 desarrolladores, la migración duró 9 meses, con lanzamientos semanales continuos durante todo el período. Resultados medidos al final del proyecto: paquete inicial reducido en 38% (de 2,4 MB a 1,5 MB gzip) después de eliminar completamente AngularJS, el tiempo de carga (tiempo de interacción) mejoró en 44%, la cobertura de prueba pasó de 22% a 68% gracias a las nuevas pruebas introducidas al mismo tiempo que cada componente migrado. Esfuerzo estimado: aproximadamente 1400 personas/horas en total, de los cuales el 60% se concentró en los módulos comerciales principales migrados en la segunda mitad del proyecto.
Preguntas frecuentes
¿Cuánto tiempo lleva una migración de AngularJS a Angular?
Varía desde unas pocas semanas para aplicaciones pequeñas hasta más de un año para aplicaciones empresariales grandes; El patrón estrangulador te permite distribuir el esfuerzo en múltiples sprints sin bloquear los lanzamientos.
¿Tengo que usar ngUpgrade?
No, sólo si elige el enfoque incremental. Con el big bang no hay necesidad, porque no hay ningún período de coexistencia entre los dos marcos.
¿Es obligatorio NgRx después de la migración?
No: Para la mayoría de las aplicaciones, los servicios con BehaviorSubject o señal son suficientes; NgRx solo es adecuado para estados muy complejos compartidos entre muchas funciones.
¿Puedo migrar sólo algunas páginas y dejar las demás en AngularJS a largo plazo?
Técnicamente sí con ngUpgrade, pero no se recomienda como estado permanente: aumenta la complejidad del mantenimiento y el paquete sigue siendo más pesado de lo necesario.
¿Cómo manejo bibliotecas de terceros específicas de AngularJS?
Deben reemplazarse con el equivalente de Angular o una biblioteca independiente del marco; no existe traducción automática para bibliotecas como restangular o angular-translate.
¿Aún se puede utilizar el transportador para pruebas E2E?
Está obsoleto por el equipo de Angular: para nuevos proyectos o migraciones recomendamos Cypress, que no depende del marco y prueba la aplicación como lo haría un usuario real.
¿Cuál es la diferencia entre downgradeComponent y UpgradeComponent?
downgradeComponent hace que un componente Angular se pueda utilizar en una plantilla AngularJS; upgradeComponent realiza la operación inversa, para reutilizar temporalmente los componentes de AngularJS en Angular.
¿Cuándo es mejor elegir el big bang en lugar del patrón estrangulador?
En aplicaciones pequeñas y medianas, con un equipo dedicado a tiempo completo y tolerancia al riesgo empresarial, donde es aceptable bloquear temporalmente las versiones.
¿Cómo evito que el manojo crezca demasiado durante la fase híbrida?
Supervise el tamaño del paquete en cada hito con un analizador de paquetes y programe explícitamente la eliminación de AngularJS tan pronto como se migre el último módulo.
¿Necesita reescribir todas las pruebas durante la migración?
No: las pruebas de AngularJS existentes siguen siendo válidas hasta que se migre el módulo correspondiente; Se agregan progresivamente nuevas pruebas de Jest/Cypress para el código Angular.
6 respuestas rápidas para fragmentos destacados y asistentes de IA
¿Qué es ngUpgrade?
ngUpgrade es el paquete oficial de Angular (@angular/upgrade) que permite que una aplicación AngularJS y una aplicación Angular se ejecuten simultáneamente en la misma página, compartiendo componentes y servicios. Es la herramienta clave para migrar incrementalmente sin bloquear las versiones, a través de downgradeComponent y upgradeComponent.
¿Cuál es el patrón estrangulador aplicado a la interfaz?
El patrón estrangulador es una estrategia de migración incremental en la que la nueva aplicación (Angular) "envuelve" progresivamente la heredada (AngularJS), reemplazando un módulo a la vez hasta que el código anterior se elimina por completo. Reduce el riesgo en comparación con una reescritura completa (big bang).
¿Cuál es la principal diferencia entre los componentes $scope y Angular?
$scope en AngularJS es un objeto compartido y mutable que conecta controladores y plantillas con un enlace bidireccional generalizado. En Angular, el estado vive como propiedades escritas de la clase de componente, con enlace explícito ([valor], (evento)) y detección de cambios aislados por componente, más predecible y eficaz.
¿Cómo se reemplaza $http en Angular?
Con HttpClient, inyectado mediante inyección de dependencia en los servicios. La principal diferencia es que HttpClient devuelve Observable de RxJS en lugar de promesa, lo que permite a operadores como retry, debounceTime y switchMap para manejar solicitudes complejas.
¿Cómo se maneja la autenticación durante el período híbrido?
Centralizando tokens y lógica de inicio de sesión en un único AuthService Angular, también expuesto a AngularJS a través de downgradeInjectable. De esta manera, tanto AngularJS como las páginas de Angular comparten el mismo estado de autenticación sin duplicar código.
¿Cuánto cuesta una migración AngularJS → Angular en términos de esfuerzo?
Depende del tamaño: las aplicaciones pequeñas requieren algunas semanas, las aplicaciones empresariales con cientos de controladores pueden requerir más de 1000 horas-persona repartidas en 6 a 12 meses con un enfoque incremental, manteniendo activas las nuevas funciones a lo largo del camino.
Errores comunes que se deben evitar
- Migrar sin auditoría previa: comenzar a escribir componentes Angular sin tener dependencias mapeadas y problemas críticos conduce a estimaciones erróneas y bloqueos a mitad de camino.
- Elegir el big bang de una aplicación demasiado grande: bloquea los lanzamientos durante meses y aumenta drásticamente el riesgo de regresiones no descubiertas a tiempo.
- Olvidar eliminar AngularJS al final de la migración: el paquete permanece inflado durante meses porque nadie eliminó la dependencia
angularenpackage.json. - No centralizar el estado compartido (autenticación, usuario actual): duplicar la lógica entre los dos marcos durante la fase híbrida genera errores de sincronización difíciles de diagnosticar.
- Descuidar las pruebas E2E durante el período híbrido: es precisamente en esta etapa cuando el riesgo de regresión es mayor, no después.
- Traducir directivas 1:1 sin repensar la arquitectura: algunas directivas de AngularJS esconden más responsabilidades que en Angular deberían separarse en distintos componentes.
- Subestimar la curva de aprendizaje del equipo: decorador, DI mecanografiado y RxJS requieren capacitación dedicada, no solo "aprender haciendo" bajo presión de fecha límite.
- No monitorear el tamaño del paquete durante la migración: sin verificación automática en CI, un aumento anómalo pasa desapercibido hasta que se lanza a producción.
Lista de verificación operativa y plan de 30/60/90 días
| Fase | Objetivo | KPI de referencia |
|---|---|---|
| Días 1-30 | Auditoría completa, elección de estrategia, configuración del entorno y arranque híbrido con ngUpgrade | Arranque híbrido trabajando en etapas, inventario completo de módulos |
| Días 31-60 | Migración de los primeros 3-5 módulos periféricos (baja criticidad), introducción de pruebas Jest/Cypress | Prueba de cobertura no inferior al nivel pre-migración |
| Días 61-90 | Migración de autenticación y enrutamiento central, primer módulo empresarial central migrado | 0 regresiones críticas en producción, paquete monitoreado en cada versión |
Actividades recurrentes: todos los días monitorea cualquier error en producción en los módulos ya migrados; realizar semanalmente una auditoría del tamaño del paquete y una prueba de cobertura; cada mes revise la hoja de ruta de migración con el equipo y actualice la calificación de criticidad de los módulos restantes.
Herramientas y recursos útiles
- CLI angular
- ngUpgrade (@angular/upgrade)
- TypeScript
- ESLint
- Más bonita
- Ciprés
- Faro
- Analizador de paquetes (explorador de mapas de origen o analizador de paquetes de paquetes web)
Datos estructurados y SEO técnico
Para un artículo técnico de este tipo, los datos estructurados del artículo y de la página de preguntas frecuentes ayudan tanto a su clasificación en Google como a la probabilidad de ser citado por los asistentes de conversación que analizan la página.
Ejemplo de artículo JSON-LD
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "Migrazione da AngularJS a Angular: guida completa, strategia e best practice",
"description": "Guida pratica alla migrazione da AngularJS ad Angular: strategia, ngUpgrade, routing, auth, testing, checklist 30/60/90 giorni.",
"author": { "@type": "Organization", "name": "Nome Azienda" },
"datePublished": "2026-08-07",
"dateModified": "2026-08-07",
"mainEntityOfPage": "https://www.esempio.it/blog/migrazione-angularjs-angular"
}
Etiquetas recomendadas de Open Graph
| Etiqueta | Valor recomendado |
|---|---|
| og:title | Migración de AngularJS → Angular: Guía completa |
| og:description | Estrategia, ngUpgrade, mapeo conceptual y lista de verificación operativa para migrar sin detener lanzamientos. |
| og:image | Imagen dedicada 1200x630px, no el logotipo de la empresa |
| URL recomendada | /migración-angularjs-angular |
Cómo comprobar
- Prueba móvil: verifique la representación y el rendimiento de la aplicación híbrida en un dispositivo real, no solo en emulación.
- Verificación de esquema: valide el artículo/página de preguntas frecuentes JSON-LD con la herramienta de prueba de datos estructurados de Google.
- Compruebe el tamaño del paquete: compare el tamaño del paquete antes/después de cada hito con un analizador de paquetes, para interceptar el crecimiento anómalo.
- ngPrueba de integración de actualización: Verifique que los componentes y servicios compartidos entre AngularJS y Angular funcionen correctamente en ambas direcciones (degradar y actualizar).
- Verificar la cobertura de la prueba: La cobertura general nunca debe caer por debajo del nivel previo a la migración durante todo el viaje.
- Auditoría de rendimiento de Lighthouse: realice una auditoría de Lighthouse en cada hito, comparando el tiempo hasta la pintura interactiva y de mayor contenido con la línea base de AngularJS.
Conclusión: por dónde empezar
La migración de AngularJS a Angular no es un proyecto improvisado: requiere una auditoría honesta del código existente, una estrategia elegida en función del tamaño y la tolerancia al riesgo, y herramientas como ngUpgrade que hacen posible una transición incremental sin bloquear el negocio. Comience con la auditoría, elija el patrón estrangulador si la aplicación es grande y migre un módulo periférico de baja criticidad como primer paso concreto. Si prefiere una comparación directa sobre su caso específico, solicite una auditoría de migración o descargue la lista de verificación operativa de esta guía para comenzar a aplicarla inmediatamente a su proyecto.