Best practices per sviluppare in Angular

  • Di
  • 2025-01-09 - 5 minuti
banner

Per garantire che il tuo progetto Angular segua le best practices, dovresti concentrarti su diverse aree chiave che migliorano la sicurezza, le prestazioni e la manutenibilità.

In questo post raccontiamo quali sono quelle più importanti.

Qualità del Codice

  • Naming convention: Mantenere una nomenclatura uniforme per file e variabili.
  • Limitare la dimensione dei componenti: Mantenere i file sotto le 400 righe e le funzioni sotto le 75 righe per migliorare la leggibilità.
  • Evitare l’uso estensivo tipo ‘any’: TypeScript è un linguaggio tipizzato, per cui è importante utilizzare tipi specifici per ridurre i bug e migliorare il refactoring.

Ottimizzazione delle Prestazioni

  • Lazy Loading: Implementare il lazy loading per i moduli per migliorare i tempi di caricamento iniziali.
  • Utilizzare trackBy con ngFor: Ottimizzare le prestazioni di rendering prevenendo aggiornamenti non necessari del DOM. Un esempio è il seguente:

Immagina di avere un file TypeScript di un componente (track-by-example.component.ts) dove definisci un array di prodotti.

import { Component, OnInit } from '@angular/core';
export interface Product {
	id: number;
	name: string;
}
@Component({
	selector: 'app-track-by-example',
	templateUrl: './track-by-example.component.html',
})
export class TrackByExampleComponent implements OnInit {

	products: Product[] = [
		{ id: 1, name: 'Prodotto A' },
		{ id: 2, name: 'Prodotto B' },
		{ id: 3, name: 'Prodotto C' },
	];

	ngOnInit() {
		// Emula l'aggiunta di un prodotto alla lista
		setTimeout(() => {
			this.products.push({ id: 4, name: 'Prodotto D' });
			this.products[1].name = 'Prodotto B Aggiornato'; // Aggiorna un elemento esistente
		}, 2000);
	}

	trackByProductId(index: number, product: Product): number {
		return product.id; // ID unico per ogni prodotto
	}

}

Esempio editato da Gregorio Giorgino

Nel file HTML del tuo componente (track-by-example.component.html), utilizza la direttiva *ngFor insieme alla funzione trackBy.

<ul>
  <li *ngFor="let product of products; trackBy: trackByProductId">
    {{ product.name }}
  </li>
</ul>

La funzione trackByProductId restituisce un ID (ossia product.id) per ogni elemento. Questo aiuta Angular a tenere traccia di quali elementi sono cambiati, stati aggiunti o rimossi, così che si possa ottimizzare il rendering aggiornando solo gli elementi del DOM che sono cambiati invece di caricare nuovamente l’intero elenco.

  • Caching delle chiamate verso le API: Memorizzare nella cache le risposte delle API che non cambiano frequentemente per migliorare le prestazioni di risposte dell’applicazione. Ad esempio, è possibile usare RxJS per configure il caching delle chiamate, come visibile in questo esempio.
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { shareReplay, catchError } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class ApiService {
  private cache$: Observable<any>;

  constructor(private http: HttpClient) {}

  getData(apiUrl: string): Observable<any> {
    if (!this.cache$) {
      this.cache$ = this.http.get(apiUrl).pipe(
        shareReplay(1),
        catchError(error => {
          console.error('Error fetching data:', error);
          throw error;
        })
      );
    }
    return this.cache$; 
  }

  clearCache() {
    this.cache$ = null; 
  }
}

Il metodo getData controlla se cache$ è già definito. In caso contrario, effettua una richiesta HTTP GET e memorizza nella cache il risultato tramite shareReplay(1), che memorizza l’ultimo valore emesso. L’operatore catchError registra tutti gli errori che si verificano durante la richiesta, mentre il metodo clearCache consente di svuotare la cache ogni volta che è necessario.

Struttura e Organizzazione del Progetto

  • Organizzare per feature: Strutturare i file in base alle funzionalità piuttosto che ai componenti per migliorare la scalabilità.
  • Utilizzare Angular CLI per generare componenti e servizi: Sfruttare Angular CLI per una configurazione coerente del progetto e generazione dei file, piuttosto che crearli manualmente.

Sicurezza

  • Content Security Policy (CSP): Applicare una CSP rigorosa per mitigare i rischi di XSS. Questo significa, -ad esempio- utilizzare degli header specifici per far sì che il contenuto di una response venga caricato solo se l’origine della request coincide con il dominio dell’applicazione:

Content-Security-Policy: default-src 'self';

  • Validazione e sanitization degli input: Validare gli input degli utenti per prevenire attacchi, utilizzando -ad esempio- i validatori messi a disposizione dai form Reactive.
  • Usare sempre HTTPS: Assicurarsi che tutte le trasmissioni di dati siano crittografate utilizzando HTTPS.
  • Usare degli Interceptor per sfruttare i token (come JWT) che controllino ogni request in ingresso, assicurando una comunicazione sicura con il back-end.
  • Usare dei Route Guards per gestire l’accesso ai componenti dell’applicazione in maniera granulare, a seconda dei ruoli dell’utente.
  • Aggiornamenti regolari delle dipendenze: Mantenere aggiornati Angular e le sue dipendenze per le patch di sicurezza.

Design dei Componenti

  • Principio della Singola Responsabilità: Suddividere i componenti in parti più piccole e riutilizzabili. Una buona applicazione di questo pattern implica la creazione di componenti che si concentrano su un singolo compito o responsabilità. Ad esempio, considera un’applicazione Angular che gestisce un elenco di prodotti: questo dovrebbe mostrare l’elenco dei prodotti e quindi definire i soli elementi necessari a questa attività, come visibile di seguito:
@Component({
  selector: 'app-item-list',
  templateUrl: './item-list.component.html',
})
export class ItemListComponent {
  @Input() items: Item[];

    constructor(private itemService: ItemService) {}

    ngOnInit(): void {
        this.itemService.getItems().subscribe((items) => {
            this.items = items;
        });
    }
}

In questo caso, dove il pattern non viene applicato, si va invece ad aggiungere della logica per poter aggiungere dei prodotti all’elenco, andando quindi ad aumentare le responsabilità del componente:

@Component({
    selector: 'app-item-list',
    templateUrl: './item-list.component.html',
})
export class ItemListComponent implements OnInit {
    items: Item[] = [];

    constructor(private itemService: ItemService) {}

    ngOnInit(): void {
        this.itemService.getItems().subscribe((items) => {
            this.items = items;
        });
    }

    addItem(name: string): void {
        this.itemService.addItem(name).subscribe((item) => {
            this.items.push(item);
        });
    }
}

Documentazione e Test

  • Documentazione: Mantenere una documentazione chiara per il codice e i componenti, a partire dal README.md fino alla documentazione utente.
  • Test Unitari: Implementare test unitari per garantire che la funzionalità rimanga intatta durante le modifiche.

E tu, conosci qualche altra best practice da condividere?

Post correlati

TheRedCode.it - Il mondo #tech a piccoli #bit

Partners

Community, aziende e persone che supportano attivamente il blog

Logo di Codemotion
Logo di GrUSP
Logo di Python Milano
Logo di Schrodinger Hat
Logo di Python Biella Group
Logo di Fuzzy Brains
Logo di Django Girls
Logo di Improove
Logo del libro open source
Logo di NgRome
Logo de La Locanda del Tech
Logo di Tomorrow Devs
Logo di Coderful
Logo di VueSchool

Non perderti gli ultimi aggiornamenti, iscriviti a TheRedCode Digest!

La tecnologia corre, e tu devi correre più veloce per rimanere sempre sul pezzo! 🚀

Riceverai una volta al mese (o anche meno) con codici sconto per partecipare agli eventi del settore, quiz per vincere dei gadget e i recap degli articoli più interessanti pubblicati sul blog

Ci sto!

#TheRedComics

Edizione di Gennaio - Buon Anno nuovo!

A cura di Sophie Aiello, copy di Chiara Romano

Fumetto di dicembre di Sophie Aiello, Copy di Chiara Romano

Vuoi diventare #tech content creator? 🖊️

Se vuoi raccontare la tua sul mondo #tech con dei post a tema o vuoi condividere la tua esperienza con la community, sei nel posto giusto! 😉

Manda una mail a collaborazioni[at]theredcode.it con la tua proposta e diventa la prossima penna del blog!

Ma sì, facciamolo!