È uscito il Corso SQL Completo

Struttura del Progetto

Panoramica della Struttura

Quando si crea un nuovo progetto con ng new, Angular CLI genera una struttura di cartelle ben organizzata. Comprendere ogni file e cartella è fondamentale per lavorare efficacemente.

mia-app/
├── node_modules/
├── src/
│   ├── app/
│   │   ├── app.component.ts
│   │   ├── app.component.html
│   │   ├── app.component.scss
│   │   ├── app.component.spec.ts
│   │   ├── app.config.ts
│   │   └── app.routes.ts
│   ├── assets/
│   ├── environments/
│   │   ├── environment.ts
│   │   └── environment.prod.ts
│   ├── index.html
│   ├── main.ts
│   └── styles.scss
├── angular.json
├── package.json
├── tsconfig.json
├── tsconfig.app.json
├── tsconfig.spec.json
└── README.md

File di Root

main.ts

Il file main.ts è il punto di ingresso dell’applicazione. Qui viene effettuato il bootstrap dell’applicazione.

// Approccio standalone (Angular 17+)
import { bootstrapApplication } from '@angular/platform-browser';
import { appConfig } from './app/app.config';
import { AppComponent } from './app/app.component';

bootstrapApplication(AppComponent, appConfig)
  .catch((err) => console.error(err));

Con l’approccio basato su NgModules (versioni precedenti):

// Approccio NgModule (legacy)
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';

platformBrowserDynamic()
  .bootstrapModule(AppModule)
  .catch((err) => console.error(err));

index.html

Il file HTML principale che ospita l’applicazione Angular:

<!DOCTYPE html>
<html lang="it">
<head>
  <meta charset="utf-8">
  <title>MiaApp</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
  <app-root></app-root>
</body>
</html>

Il tag <app-root> è il selettore del componente root dell’applicazione. Angular sostituisce questo tag con il template del componente principale.

styles.scss

Il file di stili globali dell’applicazione. Gli stili definiti qui si applicano a tutti i componenti:

// styles.scss - Stili globali
@import 'variables';

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: 'Segoe UI', Tahoma, sans-serif;
  line-height: 1.6;
  color: #333;
}

La Cartella app/

app.config.ts

Il file di configurazione principale dell’applicazione (approccio standalone):

import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideHttpClient, withInterceptors } from '@angular/common/http';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
import { routes } from './app.routes';
import { authInterceptor } from './interceptors/auth.interceptor';

export const appConfig: ApplicationConfig = {
  providers: [
    provideZoneChangeDetection({ eventCoalescing: true }),
    provideRouter(routes),
    provideHttpClient(withInterceptors([authInterceptor])),
    provideAnimationsAsync()
  ]
};

app.routes.ts

Il file di definizione delle rotte dell’applicazione:

import { Routes } from '@angular/router';

export const routes: Routes = [
  { path: '', redirectTo: 'home', pathMatch: 'full' },
  {
    path: 'home',
    loadComponent: () =>
      import('./pages/home/home.component').then(m => m.HomeComponent)
  },
  {
    path: 'prodotti',
    loadComponent: () =>
      import('./pages/prodotti/prodotti.component').then(m => m.ProdottiComponent)
  },
  { path: '**', redirectTo: 'home' }
];

app.component.ts

Il componente root dell’applicazione:

import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { HeaderComponent } from './components/header/header.component';
import { FooterComponent } from './components/footer/footer.component';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [RouterOutlet, HeaderComponent, FooterComponent],
  template: `
    <app-header />
    <main>
      <router-outlet />
    </main>
    <app-footer />
  `,
  styleUrl: './app.component.scss'
})
export class AppComponent {
  titolo = 'mia-app';
}

Approccio NgModule (Legacy)

Per i progetti che utilizzano ancora NgModules, la struttura include app.module.ts:

// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    HttpClientModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {}

Cartella Environments

La cartella environments/ contiene i file di configurazione per ambienti diversi.

// environments/environment.ts (sviluppo)
export const environment = {
  production: false,
  apiUrl: 'http://localhost:3000/api',
  debugMode: true,
  sentryDsn: ''
};
// environments/environment.prod.ts (produzione)
export const environment = {
  production: true,
  apiUrl: 'https://api.miaapp.it/api',
  debugMode: false,
  sentryDsn: 'https://xxx@sentry.io/123'
};

L’uso nei servizi:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { environment } from '../../environments/environment';

@Injectable({ providedIn: 'root' })
export class ApiService {
  private baseUrl = environment.apiUrl;

  constructor(private http: HttpClient) {}

  getProdotti() {
    return this.http.get(`${this.baseUrl}/prodotti`);
  }
}

La sostituzione dei file viene configurata in angular.json:

"configurations": {
  "production": {
    "fileReplacements": [
      {
        "replace": "src/environments/environment.ts",
        "with": "src/environments/environment.prod.ts"
      }
    ]
  }
}

Cartella Assets

La cartella assets/ contiene file statici come immagini, font, file JSON e altro che vengono copiati nella build finale senza modifiche.

src/assets/
├── images/
│   ├── logo.svg
│   └── hero-banner.jpg
├── fonts/
│   └── custom-font.woff2
├── i18n/
│   ├── it.json
│   └── en.json
└── data/
    └── config.json

Per includere file o cartelle aggiuntive nella build, configurali in angular.json:

"assets": [
  "src/favicon.ico",
  "src/assets",
  {
    "glob": "**/*",
    "input": "node_modules/libreria/assets",
    "output": "/assets/libreria"
  }
]

Struttura Consigliata per Progetti Grandi

Per applicazioni enterprise, una struttura ben organizzata è fondamentale:

src/app/
├── core/                    # Servizi singleton, guard, interceptor
│   ├── guards/
│   │   └── auth.guard.ts
│   ├── interceptors/
│   │   └── auth.interceptor.ts
│   ├── services/
│   │   ├── auth.service.ts
│   │   └── notification.service.ts
│   └── models/
│       ├── utente.model.ts
│       └── prodotto.model.ts
├── shared/                  # Componenti, direttive, pipe riutilizzabili
│   ├── components/
│   │   ├── bottone/
│   │   ├── card/
│   │   └── modale/
│   ├── directives/
│   │   └── evidenzia.directive.ts
│   └── pipes/
│       └── tronca.pipe.ts
├── features/                # Moduli feature (pagine/sezioni)
│   ├── home/
│   │   ├── home.component.ts
│   │   ├── home.component.html
│   │   └── home.component.scss
│   ├── prodotti/
│   │   ├── lista-prodotti/
│   │   ├── dettaglio-prodotto/
│   │   └── services/
│   │       └── prodotti.service.ts
│   └── admin/
│       ├── dashboard/
│       └── gestione-utenti/
├── layouts/                 # Layout dell'applicazione
│   ├── main-layout/
│   └── admin-layout/
├── app.component.ts
├── app.config.ts
└── app.routes.ts

Principi di organizzazione

// core/models/utente.model.ts
export interface Utente {
  id: number;
  nome: string;
  cognome: string;
  email: string;
  ruolo: 'admin' | 'utente' | 'moderatore';
}

// core/services/auth.service.ts
@Injectable({ providedIn: 'root' })
export class AuthService {
  // Servizio singleton disponibile ovunque
}

// shared/components/bottone/bottone.component.ts
@Component({
  selector: 'app-bottone',
  standalone: true,
  template: `
    <button [class]="variante" [disabled]="disabilitato">
      <ng-content />
    </button>
  `
})
export class BottoneComponent {
  @Input() variante: 'primario' | 'secondario' = 'primario';
  @Input() disabilitato = false;
}

Best Practices

  • Separa il codice in core, shared e features per una chiara organizzazione
  • I servizi singleton vanno nel modulo core con providedIn: 'root'
  • I componenti riutilizzabili vanno nella cartella shared
  • Ogni feature dovrebbe essere auto-contenuta con i propri componenti e servizi
  • Usa il lazy loading per le feature route per ridurre il bundle iniziale
  • Mantieni i file di configurazione degli ambienti separati e non committare mai segreti
  • Segui una naming convention consistente: nome-componente.component.ts, nome-servizio.service.ts
  • Utilizza barrel exports (index.ts) per semplificare gli import nelle cartelle condivise