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