Guía práctica: cómo migré un proyecto de Angular 19/20 a Angular 21.2 sin morir en el intento
Migrar un proyecto Angular de v19/20 a v21 puede sonar intimidante. En la práctica, si seguís el proceso correcto, es incremental: cada paso es reversible y el proyecto sigue funcionando en todo momento. Esta es la guía que apliqué en proyectos reales.
Antes de empezar: el inventario
# Ver versión actual y dependencias desactualizadas
ng version
ng update
# Verificar compatibilidad antes de actualizar
npx npm-check-updates -u --target minor
Paso 1: Actualizar el core
# Siempre de a una versión mayor a la vez
# Si estás en v19, primero actualizar a v20, luego a v21
# De v20 a v21:
ng update @angular/core@21 @angular/cli@21
# El comando aplica schematics automáticos:
# - Actualiza imports deprecated
# - Adapta APIs que cambiaron
# - Avisa sobre cambios manuales necesarios
# Verificar que compila
ng build --configuration production
Paso 2: Adoptar Zoneless
// app.config.ts
import { provideZonelessChangeDetection } from '@angular/core';
export const appConfig: ApplicationConfig = {
providers: [
provideZonelessChangeDetection(),
provideRouter(routes)
]
};
// angular.json: "polyfills": [] // eliminar zone.js
// npm uninstall zone.js
Paso 3: Migrar de Karma a Vitest
ng generate @angular/build:vitest
ng test # verificar que los tests pasan
npm uninstall karma karma-chrome-launcher karma-coverage karma-jasmine karma-jasmine-html-reporter
Paso 4: Standalone components
# Angular 21 asume standalone por defecto
# Migración automática:
ng generate @angular/core:standalone --mode=convert-to-standalone
ng generate @angular/core:standalone --mode=prune-ng-modules
ng generate @angular/core:standalone --mode=standalone-bootstrap
Checklist completo
| Paso | Acción | Obligatorio |
|---|---|---|
| 1 | ng update @angular/core@21 @angular/cli@21 | ✅ Sí |
| 2 | Verificar que la app compila y los tests pasan | ✅ Sí |
| 3 | Activar provideZonelessChangeDetection() | Recomendado |
| 4 | Eliminar Zone.js de polyfills | Con paso 3 |
| 5 | Migrar a Vitest | Recomendado |
| 6 | Nuevos formularios con Signal Forms | Gradual |
| 7 | Componentes de nav con funciones standalone del Router | Gradual |
| 8 | Configurar ng mcp para integración con IA | Opcional |
Errores comunes y cómo resolverlos
// ERROR: El componente no se actualiza después de activar Zoneless
// → Convertir estado a Signals o llamar markForCheck()
// ERROR: Tests fallan con "No current Angular test" después de Vitest
// → Verificar imports de @angular/core/testing
// ERROR: "Cannot find module zone.js"
// → Buscar y eliminar import 'zone.js' en el proyecto:
// grep -r "import 'zone.js'" src/
// ERROR: ExpressionChangedAfterItHasBeenCheckedError en Zoneless
// → Usar signal.update() o signal.set() en lugar de mutación directa
Mi experiencia: cuánto tardó la migración
En un proyecto de tamaño medio (45 componentes, 12 servicios, 80 tests): el ng update tardó 10 minutos. Revisar avisos y corregir deprecaciones: media jornada. Migración a Zoneless con todos los tests adaptados a Vitest: un día. Adopción gradual de Signal Forms en los formularios principales: dos semanas, a medida que tocábamos cada módulo.
No es un proceso de un fin de semana, pero tampoco es una reescritura. Es una evolución incremental que podés hacer en paralelo con el trabajo normal del equipo.
← Artículo anterior: Router Signals en Angular 21: navegación standalone sin cargar todo el Router | Fin de la Serie Angular 20 → 21.2
¿Tenés preguntas sobre la migración en tu proyecto específico? Dejá tu caso en los comentarios. 👇

Dejar un comentario
¿Quieres unirte a la conversación?Siéntete libre de contribuir!