Angular 21: la era de los signals y standalone
Angular 21 marca un punto de inflexion en la historia del framework. Con standalone como comportamiento por defecto, un sistema de signals maduro y mejoras significativas en rendimiento, Angular se posiciona como una opcion moderna y pragmatica para aplicaciones empresariales.
Standalone por defecto
El cambio más visible de Angular 21 es que todos los componentes, directivas y pipes son standalone por defecto. Ya no necesitas declarar standalone: true en el decorador.
// Angular 20 y anteriores
@Component({
standalone: true, // necesario
selector: 'app-hello',
template: `<h1>Hola {{ name() }}</h1>`,
})
export class HelloComponent { }
// Angular 21
@Component({
selector: 'app-hello',
template: `<h1>Hola {{ name() }}</h1>`,
})
export class HelloComponent { } // standalone por defectoQué pasa con los NgModules?
Los NgModules siguen funcionando pero son considerados legacy. Angular proporciona un schematic de migración:
ng generate @angular/core:standalone-migrationEste comando convierte automaticamente tus componentes NgModule a standalone, actualizando imports y providers.
Sistema de Signals maduro
Angular 21 consolida el sistema de signals con nuevas APIs y mejoras de rendimiento.
Signal Inputs
Los signal inputs reemplazan al decorador @Input() con una API basada en signals:
// Antes: decorador @Input
@Input() title: string = '';
@Input({ required: true }) id!: number;
// Angular 21: signal inputs
title = input<string>('');
id = input.required<number>();Ventajas:
- Son signals, por lo que se pueden usar en
computed()yeffect() - Tipado más estricto
- Mejor integración con OnPush
Signal Outputs
Similar a inputs, los outputs ahora tienen una API funcional:
// Antes
@Output() save = new EventEmitter<FormData>();
// Angular 21
save = output<FormData>();linkedSignal
linkedSignal es una nueva API que crea un signal que se sincroniza con otro, pero permite escritura local:
const selectedCountry = signal('Bolivia');
// Se actualiza cuando selectedCountry cambia, pero se puede escribir
const selectedCity = linkedSignal(() => {
const country = selectedCountry();
return country === 'Bolivia' ? 'Oruro' : 'Desconocida';
});
// Escritura local
selectedCity.set('La Paz'); // funciona
// Pero si selectedCountry cambia, se recalcula
selectedCountry.set('Peru'); // selectedCity vuelve a 'Desconocida'Signal queries
Las queries del DOM ahora también son signals:
// Antes
@ViewChild('myInput') myInput!: ElementRef;
@ViewChildren(ItemComponent) items!: QueryList<ItemComponent>;
// Angular 21
myInput = viewChild<ElementRef>('myInput');
items = viewChildren(ItemComponent);
// Se pueden usar en computed
isEmpty = computed(() => this.items().length === 0);Mejoras en hidratacion y SSR
Hidratacion incremental
Angular 21 introduce hidratacion incremental, que permite hidratar componentes bajo demanda en lugar de toda la página de golpe:
@Component({
selector: 'app-comments',
template: `
@defer (hydrate on viewport) {
<app-comment-list [comments]="comments()" />
}
`,
})
export class CommentsComponent {
comments = input.required<Comment[]>();
}Los triggers de hidratacion disponibles son:
| Trigger | Descripcion |
|---|---|
hydrate on idle |
Cuando el navegador esta idle |
hydrate on viewport |
Cuando el elemento entra al viewport |
hydrate on interaction |
Al interactuar (click, focus, etc.) |
hydrate on hover |
Al pasar el cursor |
hydrate on timer(ms) |
Despues de un tiempo |
hydrate never |
Solo contenido estático, sin hidratar |
Event replay
Durante la hidratacion, Angular ahora captura y reproduce eventos del usuario. Si un usuario hace click en un boton antes de que se complete la hidratacion, el evento se almacena y se ejecuta cuando el componente este listo.
Control flow estable
El control flow basado en bloques es ahora la única forma recomendada:
<!-- @if reemplaza *ngIf -->
@if (user(); as u) {
<p>Bienvenido, {{ u.name }}</p>
} @else {
<p>Inicia sesión</p>
}
<!-- @for reemplaza *ngFor (requiere track) -->
@for (item of items(); track item.id) {
<app-item [data]="item" />
} @empty {
<p>No hay elementos</p>
}
<!-- @switch reemplaza ngSwitch -->
@switch (status()) {
@case ('loading') {
<app-spinner />
}
@case ('error') {
<app-error [message]="errorMsg()" />
}
@default {
<app-content [data]="data()" />
}
}Nuevas APIs de Router
withComponentInputBinding mejorado
Los parametros de ruta se inyectan automaticamente como signal inputs:
// En la configuración de rutas
provideRouter(routes, withComponentInputBinding());
// En el componente - el parametro :id se inyecta automaticamente
@Component({ ... })
export class ProductDetailComponent {
id = input.required<string>(); // se llena con el parametro :id
}Functional guards y resolvers
// Guard funcional
export const authGuard: CanActivateFn = () => {
const auth = inject(AuthService);
const router = inject(Router);
if (auth.isAuthenticated()) return true;
return router.createUrlTree(['/login']);
};
// Resolver funcional
export const productResolver: ResolveFn<Product> = (route) => {
const service = inject(ProductService);
return service.getById(route.paramMap.get('id')!);
};Guia de migración
Paso 1: Actualizar Angular CLI
ng update @angular/core@21 @angular/cli@21Paso 2: Ejecutar migraciones automaticas
# Migrar a standalone (si aun usas NgModules)
ng generate @angular/core:standalone-migration
# Migrar inputs/outputs a signals
ng generate @angular/core:signal-input-migration
ng generate @angular/core:output-migration
# Migrar control flow
ng generate @angular/core:control-flow-migrationPaso 3: Verificar cambios breaking
- Eliminar
standalone: truede todos los decoradores (ahora es el default) - Reemplazar
@HostBindingy@HostListenercon la propiedadhostdel decorador - Verificar que
inject()se usa en lugar de constructor injection
Paso 4: Optimizar para signals
- Convertir propiedades de componente a
signal() - Usar
computed()para estado derivado - Reemplazar
Subjectssimples con signals donde sea posible - Asegurar que todos los componentes usen
OnPush
Conclusion
Angular 21 completa la transición hacia un modelo reactivo basado en signals, con standalone por defecto y herramientas de migración maduras. Si vienes de versiones anteriores, las migraciones automaticas facilitan enormemente la actualizacion. Si empiezas un proyecto nuevo, Angular 21 te ofrece una experiencia de desarrollo moderna, tipada y performante desde el primer dia.



Comentarios (0)
Inicia sesión para comentar