ANGULAR 6

ARCHITECTURE & ORGANISATION DU CODE
Thibault Even - Expert Angular
ENVIRONNEMENT
• Typescript Language

• Visual Studio Code

• Angular CLI

• Plugins pour les projets Angular
• Angular Language Service

• angular2-inline

• angular v6 snippets

• prettier

• Material icon Theme / vscode-icons

• tslint

• trailing spaces
Plugins que j’utilise
pack de plugins
• Extensions packs et essentials packs
FROM SCRATCH
• Modules et composants

• Commandes CLI

• Architecture des dossiers
MODULE
COMPONENT
PIPE/

DIRECTIVE/

GUARDS
Modules et composants
MODULE 1
COMPONENT
PIPE/

DIRECTIVE/

GUARDS
Modules et composants
MODULE 2
MODULE 0
déclaration
import
export
DOMAIN

MODULE
ROUTING

MODULE
CORE

MODULE
Import unique dans app.module

Mettre tout les .forRoot() des modules tierce
SHARED

MODULE
Import dans tout les features modules

Composants et module partagés par les features modules
FEATURE

MODULE
Généralement attaché directement au app.module ou
indépendant par lazy-loading

Gère toute une partie de l’application : interface +
échange de donnée. ex : les commandes de produits
Commun à quelques features modules

Module en charge d’une fonctionnalité particulière qui
regroupe plusieurs components, services…
Module chargé de la déclaration des routes

Attaché à un feature module, optionnel, le forRoot doit
être dans le CoreModule
COMPONENT
CONTAINER
Composant chargé de récupérer et diffuser
la donnée dans les autres sous-composants

En relation avec le state-management ou les
services, pas d’input/output
Composant pouvant être utiliser dans
plusieurs application différentes

Ils ne demandent jamais la donnée
directement, ils ont des input et output pour les
événements à envoyer au composant parent

import { Component, OnInit, ChangeDetectionStrategy } from
'@angular/core';
import { Observable } from ‘rxjs';
import { FeatureService } from ‘../../services/feature.service';
import { Users } from '../../models/jsonpldr.model';
@Component({
…
})
export class Container1Component implements OnInit {
users$: Observable<Users>;
constructor(private api: FeatureService) {}
ngOnInit() {
this.users$ = this.api.getUsers();
}
CONTAINER
import { Component, OnInit, Input, Output,
EventEmitter } from '@angular/core';
@Component({
…
})
export class Component1Component implements OnInit {
@Input() data: string[];
@Output() selected = new EventEmitter<string>();
constructor() {}
ngOnInit() {}
onClick(item: string) {
this.selected.emit(item);
}
}
COMPONENT
Commandes CLI
•ng new 

•ng serve

•ng generate
•ng build

•ng update

•ng add
Commandes CLI : New
ng new ng6-project --style=scss
Commandes CLI : Serve
ng serve --port=4200
Commandes CLI : Generate
ng generate
component
module
directive
guard
pipe
service
library
application
Commandes CLI : Generate
ng generate <schematics> --dryRun
L’option dryRun alias -d
Commandes CLI : Generate
ng generate library mysharedlib --prefix=my
La nouveauté : library
Commandes CLI : Build
ng build --prod
ng build --prod --build-optimizer
dist
Commandes CLI : Update
ng update
ng update rxjs
Commandes CLI : Add
ng add @angular/material
Ajout de la librairie ET intégration dans le code 

+ ajout de générateurs
Architecture ng6 : Multi App
ng generate application mysecondapp
Commandes CLI : WIKI
github.com/angular/angular-cli/wiki
Architecture angular 6
src (Main app)
projects (librairies, sub app)
Partage des librairies entre applications, 

maintenances indépendantes
Organisation intra-app
app
core
shared
app.module.tsts
Core / Shared principes
Organisation intra-app
Core Module - unique import, root modules cfg
core
containers
core.module.tsts
app
app.component.tsts
app.component.scss
Organisation intra-app
shared
components
shared.module.tsts
Shared Module - Composants / librairies transverses
pipes
directives
Organisation intra-app
app
core
shared
app.module.tsts
Clean architecture
Organisation intra-app
components
component1
component2
index.tsts
index.ts imports/exports
Organisation intra-app
index.ts imports/exports
index.tsts
import { Component1Component } from './component1/component1.component';
import { Component2Component } from './component2/component2.component';
import { Component3Component } from './component3/component3.component';
export const components = [
Component1Component,
Component2Component,
Component3Component
];
export * from './component1/component1.component';
export * from './component2/component2.component';
export * from './component3/component3.component';
Organisation intra-app
index.ts imports/exports
my.module.tsts
import * as fromComponents from './components';
@NgModule({
exports: [
...fromComponents.components,
],
declarations: [
...fromComponents.components,
]
})
export class MyModule {}
Organisation intra-app
app
core
shared
app.module.tsts
Libs folder
libs - domain modules directory
Organisation intra-app
app
core
shared
app.module.tsts
Domain / Features modules principes
feature module
Organisation intra-app
Feature module
feature
components
feature.module.tsts
containers
services
guards
feature.routing.tsts
Organisation intra-app
Feature module
feature.module.tsts
import { NgModule } from '@angular/core';
import { SharedModule } from '../shared/shared.module';
import { FeatureRoutingModule } from './feature.routing';
import * as fromComponents from './components';
import * as fromContainers from './containers';
import * as fromGuards from './guards';
@NgModule({
imports: [SharedModule, FeatureRoutingModule],
exports: [],
declarations:
[...fromComponents.components, ...fromContainers.containers],
providers: [...fromGuards.guards]
})
export class FeatureModule {}
Organisation intra-app
Feature module
feature.routing.tsts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import * as fromContainers from './containers';
const routes: Routes = [
{ path: '', component: fromContainers.Container1Component
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class FeatureRoutingModule {}
Organisation intra-app
lazy-loaded features modules
app.component.htmlhtml
<router-outlet></router-outlet>
Organisation intra-app
lazy-loaded features modules
core.routing.tsts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
export const routes: Routes = [
{ path: '**', redirectTo: 'feature' },
{
path: 'feature',
loadChildren: '../feature/feature.module#FeatureModule'
}
];
@NgModule({
imports: [RouterModule.forRoot(routes, { useHash: false })],
exports: [RouterModule]
})
export class CoreRoutingModule {}
Rxjs 6
refactoring des imports
// CREATION - RECREATION
import { Observable, throwError, BehaviorSubject } from ‘rxjs';
// OPERATORS
import { catchError, tap, map, retry, delay } from 'rxjs/operators';
Rxjs 6
using .pipe
getUsers() {
return this.httpClient
.get<Users>(this.api_url + '/users', {
observe: 'response'
})
.pipe(
delay(2000),
tap(response => console.log(response)),
map(response => response.body),
retry(2),
catchError((error: HttpErrorResponse) => throwError(error))
);
}
Pour aller plus loin
• https://github.com/ngrx/platform - State management - Redux pattern

• https://docs.nestjs.com/ - Nodejs framework inspiré par Angular

• https://www.apollographql.com/ - GraphQL client pour angular et bien
d’autres

• http://reactivex.io/rxjs/manual/overview.html#choose-an-
operator - Aide interactive pour choisir le bon operator Rxjs

• angular universal / angular PWA / angular Element /
Electron / Cordova /Capacitor
MERCI

A bientôt !
Thibault Even - Expert Angular


@thibault_ev

www.linkedin.com/in/thibault-even-543b3520

Meetup SkillValue - Angular 6 : Bien démarrer son application