Volver al blog
Angular Architecture Standalone Refactoring
Imagen de portada del artículo: Arquitectura sin Módulos: Guía de Componentes Standalone

Arquitectura sin Módulos: Guía de Componentes Standalone

11 min
German

Durante mucho tiempo, los NgModules fueron una barrera de entrada alta para nuevos desarrolladores y una fuente de complejidad en aplicaciones grandes. Los Standalone Components cambian las reglas del juego permitiendo que componentes, directivas y pipes sean independientes.

¿Qué es un componente Standalone?

Es un componente que no necesita ser declarado en un NgModule. Define sus propias dependencias directamente.

typescript
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HeaderComponent } from './header.component';

@Component({
  selector: 'app-home',
  standalone: true,
  imports: [CommonModule, HeaderComponent], // Importamos lo que usamos aquí
  template: `
    <app-header></app-header>
    <h1>Bienvenido a la Home</h1>
  `
})
export class HomeComponent {}

Ventajas de Standalone

Bootstrap de la Aplicación

En una aplicación totalmente Standalone, ya no necesitamos AppModule. El archivo main.ts cambia la forma de iniciar la app:

typescript
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { provideHttpClient, withInterceptors } from '@angular/common/http';
import { provideRouter, withComponentInputBinding } from '@angular/router';
import { routes } from './app/app.routes';
import { authInterceptor } from './app/interceptors/auth.interceptor';

bootstrapApplication(AppComponent, {
  providers: [
    provideRouter(routes, withComponentInputBinding()),
    provideHttpClient(withInterceptors([authInterceptor])),
    provideAnimationsAsync(),
  ]
}).catch(err => console.error(err));

Observa cómo provideRouter y provideHttpClient reemplazan a RouterModule.forRoot() y HttpClientModule con funciones tipadas y composables.

Lazy Loading Simplificado

El enrutamiento (Lazy Loading) se vuelve mucho más directo. Ya no necesitas cargar un módulo hijo, puedes cargar el componente directamente.

typescript
export const routes: Routes = [
  {
    path: '',
    loadComponent: () => import('./home/home.component').then(m => m.HomeComponent)
  },
  {
    path: 'admin',
    loadComponent: () => import('./admin/admin.component').then(m => m.AdminComponent)
  },
  // También puedes cargar rutas hijas sin módulos
  {
    path: 'settings',
    loadChildren: () => import('./settings/settings.routes').then(m => m.SETTINGS_ROUTES)
  }
];

Ejemplo de rutas hijas standalone

typescript
// settings/settings.routes.ts
export const SETTINGS_ROUTES: Routes = [
  {
    path: '',
    loadComponent: () => import('./settings-layout.component'),
    children: [
      { path: 'profile', loadComponent: () => import('./profile/profile.component') },
      { path: 'security', loadComponent: () => import('./security/security.component') },
      { path: '', redirectTo: 'profile', pathMatch: 'full' }
    ]
  }
];

Directivas y Pipes Standalone

No solo los componentes son standalone. También puedes crear directivas y pipes independientes:

typescript
@Directive({
  selector: '[appHighlight]',
  standalone: true
})
export class HighlightDirective {
  @HostListener('mouseenter') onMouseEnter() {
    // lógica de highlight
  }
}

@Pipe({
  name: 'capitalize',
  standalone: true
})
export class CapitalizePipe implements PipeTransform {
  transform(value: string): string {
    return value.charAt(0).toUpperCase() + value.slice(1);
  }
}

¿Debo migrar todo?

No es obligatorio migrar todo de golpe. Angular permite la interoperabilidad: puedes importar componentes standalone dentro de módulos existentes y viceversa. Sin embargo, para nuevos proyectos, Standalone es el camino recomendado por el equipo de Angular.

Angular ofrece un schematic de migración automática:

bash
ng generate @angular/core:standalone

Este comando analiza tu proyecto y convierte componentes, directivas y pipes a standalone de forma segura.