Optimización de Angular: Mejores Prácticas para 2024

4 min lecturaMatías Romero

Optimización de Angular: Mejores Prácticas para 2024

Durante mis más de 20 años desarrollando aplicaciones web, he visto cómo Angular ha evolucionado hasta convertirse en uno de los frameworks más potentes. Sin embargo, una aplicación Angular mal optimizada puede tener un rendimiento pobre. En este artículo, comparto las técnicas que uso para crear aplicaciones Angular ultra-rápidas.

Estrategia de Detección de Cambios OnPush

Una de las optimizaciones más impactantes es implementar la estrategia OnPush:

@Component({
  selector: 'app-tarjeta-usuario',
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <div class="tarjeta-usuario">
      <h3>{{ usuario.nombre }}</h3>
      <p>{{ usuario.email }}</p>
    </div>
  `
})
export class TarjetaUsuarioComponent {
  @Input() usuario!: Usuario;
}

Esta estrategia hace que Angular solo verifique el componente cuando:

  • Las propiedades de entrada cambian
  • Se disparan eventos
  • Los observables emiten nuevos valores

Lazy Loading y División de Código

Implementa lazy loading para módulos de funcionalidades:

const rutas: Routes = [
  {
    path: 'usuarios',
    loadChildren: () => import('./usuarios/usuarios.module').then(m => m.UsuariosModule)
  },
  {
    path: 'productos',
    loadComponent: () => import('./productos/productos.component').then(c => c.ProductosComponent)
  }
];

Scroll Virtual para Listas Grandes

Para listas con muchos elementos, el scroll virtual es esencial:

<cdk-virtual-scroll-viewport itemSize="50" class="viewport">
  <div *cdkVirtualFor="let item of items">{{ item.nombre }}</div>
</cdk-virtual-scroll-viewport>

Funciones TrackBy

Siempre usa funciones trackBy en bucles *ngFor:

@Component({
  template: `
    <div *ngFor="let usuario of usuarios; trackBy: trackByUsuarioId">
      {{ usuario.nombre }}
    </div>
  `
})
export class ListaUsuariosComponent {
  trackByUsuarioId(index: number, usuario: Usuario): number {
    return usuario.id;
  }
}

Análisis de Bundles

Analiza regularmente tus bundles:

ng build --configuration production --source-map
npx webpack-bundle-analyzer dist/tu-app/stats.json

Optimización de Imágenes

Usa el componente NgOptimizedImage de Angular:

<img ngSrc="/assets/hero-image.jpg" 
     width="1200" 
     height="600" 
     priority
     alt="Imagen principal">

Estrategias de Precarga

Implementa precarga inteligente:

RouterModule.forRoot(rutas, {
  preloadingStrategy: PreloadAllModules
})

Optimización de Observables

Usa operadores RxJS eficientemente:

// ❌ Evita esto
this.servicio.getDatos().subscribe(datos => {
  this.procesarDatos(datos);
});

// ✅ Mejor así
this.datos$ = this.servicio.getDatos().pipe(
  map(datos => this.procesarDatos(datos)),
  shareReplay(1)
);

Signals para Estado Reactivo

Usa Angular Signals para un estado más eficiente:

@Component({
  template: `
    <p>Contador: {{ contador() }}</p>
    <button (click)="incrementar()">+</button>
  `
})
export class ContadorComponent {
  contador = signal(0);
  
  incrementar() {
    this.contador.update(valor => valor + 1);
  }
}

Web Workers para Tareas Pesadas

Mueve cálculos complejos a Web Workers:

// worker.ts
addEventListener('message', ({ data }) => {
  const resultado = realizarCalculoComplejo(data);
  postMessage(resultado);
});

// component.ts
const worker = new Worker('./worker.ts', { type: 'module' });
worker.postMessage(datos);
worker.onmessage = ({ data }) => {
  this.resultado = data;
};

Mejores Prácticas que He Aprendido

  1. Mide primero, optimiza después - Usa Lighthouse y DevTools
  2. Implementa OnPush en componentes que no cambien frecuentemente
  3. Usa lazy loading para módulos grandes
  4. Optimiza imágenes y assets estáticos
  5. Implementa service workers para cache offline
  6. Monitoriza el rendimiento en producción

Herramientas de Monitoreo

// Métricas personalizadas
@Injectable()
export class MetricasService {
  private observer = new PerformanceObserver((list) => {
    list.getEntries().forEach((entry) => {
      console.log(`${entry.name}: ${entry.duration}ms`);
    });
  });

  constructor() {
    this.observer.observe({ entryTypes: ['measure'] });
  }
}

Resultados Medibles

Aplicando estas técnicas he logrado:

  • Reducción del 70% en el tiempo de carga inicial
  • Puntuaciones Lighthouse superiores a 95
  • Mejora del 60% en First Contentful Paint
  • Reducción del 50% en el tamaño del bundle

Conclusión

La optimización de Angular requiere un enfoque sistemático y medición constante. Las técnicas que he compartido han sido probadas en aplicaciones empresariales con millones de usuarios.

Recuerda:

  • La optimización prematura es la raíz de todos los males
  • Mide el impacto de cada optimización
  • Prioriza las optimizaciones por impacto vs esfuerzo
  • Mantén un balance entre rendimiento y mantenibilidad

¿Qué técnicas de optimización has usado en tus proyectos Angular? ¡Comparte tu experiencia en los comentarios!

Compartir este post