LIFT
La structure proposée s'appuie sur la recommandation officielle LIFT.
Do structure the application such that you can Locate code quickly, Identify the code at a glance, keep the Flattest structure you can, and Try to be DRY.
-
Locate:
Organisez le code pour que la localisation du code soit intuitive, simple et rapide.
-
Identify:
Nommez le fichier pour identifier instantanément ce qu'il représente et ce qu'il contient.
Pour ce faire, le nom du fichier doit être descriptif.
Evitez les fichiers mélangeant plusieurs composants, services, ...
-
Flat:
Conservez la structure la plus à plat aussi longtemps que possible.
Envisagez de créer des sous-dossiers lorsqu'un dossier atteint sept fichiers ou plus.
-
T-DRY (Try to be DRY):
Respectez le principe DRY.
Evitez toutefois de sacrifier la lisibilité juste pour suivre à la lettre le principe DRY.
L'arborescence des fichiers
-
app
-
core
-
constants
- constant-a.ts
- constant-b.ts
-
enums
-
guards
- auth.guard.ts
- module-import.guard.ts
- no-auth.guard.ts
-
helpers
-
interceptors
- token.interceptor.ts
- error.interceptor.ts
-
models
-
services
- service-a.service.ts
- service-b.service.ts
-
features
-
feature-a
-
components
-
scoped-component-a
- scoped-component-a.component.html|scss|ts
-
scoped-component-b
- scoped-component-b.component.html|scss|ts
-
models
- scoped-model-a.model.ts
- scoped-model-b.model.ts
-
pages
-
page-a
- page-a.component.html|scss|ts
-
page-b
- page-b.component.html|scss|ts
-
services
- scoped-service-a.service.ts
- scoped-service-b.service.ts
- feature-a-routing.module.ts
- feature-a.module.ts
- feature-a.component.html|scss|ts
-
shared
-
components
-
shared-button
- shared-button.component.html|scss|ts
-
directives
-
pages
-
page-not-found
- page-not-found.component.html|scss|ts
-
pipes
- shared.module.ts
- app.component.html|scss|ts
- app.component.module.ts
- app.routes.ts
-
assets
-
i18n
-
documents
-
icons
- custom-icon-a.svg
- custom-icon-b.svg
-
images
-
styles
-
abstract
-
base
- _color.scss
- _typographie.scss
- _utilities.scss
-
components
- component-a.scss
- component-b.scss
- shame.scss
- favicon.icon
- index.html
- maint.ts
- styles.scss
Alignez les noms de vos dossiers features sur vos routes.
Cette approche simplifie la compréhension et la navigation entre la structure des dossiers et les routes de l'application.
De plus on identifie rapidement le dossier contenant les composants et les ressources liés à un itinéraire spécifique.
Exemple concret
si vous avez les routes suivantes dans votre application :
- /dashboard
- /users
- /users/list
- /users/detail/:id
Alors organisez votre application comme ceci:
src/
|-- app/
| |-- core/ # Core module for singleton services and core functionality
| |-- shared/ # Shared module for reusable components, directives, and pipes
| |-- features/
| | |-- dashboard/ # Feature module for the /dashboard route
| | | |-- pages/ # Folder for page components in the dashboard feature
| | | |-- components/ # Folder for reusable components specific to the dashboard feature
| | | |-- services/ # Folder for services specific to the dashboard feature
| | |-- users/ # Feature module for the /users route
| | | |-- pages/ # Folder for page components in the users feature
| | | | |-- list/ # Component for the /users/list child route
| | | | |-- detail/ # Component for the /users/detail/:id child route
| | | |-- components/ # Folder for reusable components specific to the users feature
| | | |-- services/ # Folder for services specific to the users feature
|-- ...
Dans cet exemple, le routing module correspondant (users-routing.module.ts) doit définir à la fois la route parent et les routes enfants :
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { UsersComponent } from './users.component';
import { UsersListComponent } from './list/users-list.component';
import { UsersDetailComponent } from './detail/users-detail.component';
const routes: Routes = [
{
path: 'users',
component: UsersComponent,
children: [
{ path: 'list', component: UsersListComponent },
{ path: 'detail/:id', component: UsersDetailComponent },
],
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class UsersRoutingModule {}
Documentation: Angular File Structure and Best Practices
Documentation: Tips for Structuring Your Angular Project
Documentation: How to define a highly scalable folder structure for your Angular project
Documentation: Angular schematics extension VS Code
Documentation: Github: Angular Folder Structure
Documentation: Angular App Architecture: Don’t get Lost in Structure
Documentation: How to structure your Angular apps like a Googler
Documentation: Angular.io: Workspace and project file structure
Documentation: Angular.io Styleguide: Application structure and NgModules
Documentation: Angular project structure best practice
Modules
En Angular, un module est un moyen de regrouper tout le code associé à un aspect dans une unité modulaire.
Chaque module peut contenir des composants, des services, des directives, des pipes, ....
Toute application Angular a au moins un module, le module racine (root module).
Ce root module est appelé par convention AppModule
.
Même si il est possible pour les petites applications de n'avoir qu'un seul module, la pluspart des applications ont de nombreux modules.
Voici une liste non exhaustive des modules courant dans une application Angular:
-
Core module
Le CoreModule
est un module qui contient du code essentiel à l'application.
Ce core module ne doit être importé qu'une seule fois, généralement dans l'AppModule.
Ce module inclut des guards, helpers, des services utilisés dans l'ensemble de l'application, tels que le service d'authentification (auth service) ou de journalisation (loggin service).
-
Feature modules
Les FeatureModule
s sont des modules dédiés à des fonctionnalités ou à des domaines de fonctionnalité spécifiques au sein de l'application.
Ces modules aident à garder le code organisé et modulaire à mesure que l'application se développe.
Par exemple, on pourrait avoir un AccountModule pour gérer les comptes d'utilisateurs ou encore un ProductModule pour afficher des informations sur les produits.
-
Shared module
Le SharedModule
est un module qui contient du code partagé entre plusieurs feature modules.
Cela peut inclure des composants communs, des directives et des pipes qui sont utilisés à plusieurs endroits dans l'application.
Par exemple, le SharedModule pourrait contenier un composant de bouton custom ou encore un pipe de formatage de date.
Si vous constatez que votre SharedModule est devenu trop grand et difficile à gérer en raison du nombre de composants, de pipes et de directives qu'il contient, alors envisagez d'utiliser une stratégie d'organisation plus avancée.
Une approche possible consiste à diviser le module en plusieurs morceaux soit:
- en suivant une organisation de type SCAM
- en utilisant la feature Standalone component stabilisée dans la version 15 de Angular.
SCAM - Single Component Angular Module
SCAM, ou Single Component Angular Module, est un modèle de conception utilisé dans les applications Angulars qui consiste à créer un module contenant un seul composant.
L'approche du module à composant unique implique la création d'un module pour chaque composant de l'application.
Chaque module contiendra le composant, ainsi que tous les services, pipes ou directives dont dépend le composant.
Le module est ensuite importé dans tout autre module devant utiliser le composant.
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { GreetingComponent } from './greeting.component';
@NgModule({
declarations: [GreetingComponent],
imports: [CommonModule],
exports: [GreetingComponent],
})
export class GreetingModule {}
Standalone components
Un composant 'standalone' est un composant conçu pour être autonome et indépendant.
Le composant encapsule alors ses propres fonctionnalités, données et interface utilisateur.
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-greeting',
template: '<h1>Hello, {{name}}!</h1>',
})
export class GreetingComponent {
@Input() name: string;
}
Documentation Introduction to modules
Documentation Angular modularity
Documentation Standalone components