Slide 1

Slide 1 text

Angular Best Practices Thorsten Rinne - 28. September 2018

Slide 2

Slide 2 text

Hallo, ich bin Thorsten.

Slide 3

Slide 3 text

Software Architekt maibornwolff.de/augsburg München (2x) | Augsburg | Frankfurt | Berlin | Hamburg | Tunis

Slide 4

Slide 4 text

https://github.com/thorsten https://twitter.com/ThorstenRinne

Slide 5

Slide 5 text

PHP → TypeScript

Slide 6

Slide 6 text

Best Practices?

Slide 7

Slide 7 text

Unser Projekt

Slide 8

Slide 8 text

Zahlen & Fakten • Web App mit verschiedenen Backend-Systemen • Branche: Energiemanagement • Start Mitte September 2016 mit Angular 2.0.0 • 7 Frontend-Entwickler • über 80 fachliche und technische Module • über 350 Komponenten • über 2700 Unittests

Slide 9

Slide 9 text

!==

Slide 10

Slide 10 text

Angular • TypeScript • komponentenbasiertes Framework • kein $scope und keine Controller • modular aufgebaut • rxjs • angular-cli • feste Releasezyklen und Semantic Versioning

Slide 11

Slide 11 text

Angular Versionen • September 2016: 2.0 • März 2017: 4.0 • November 2017: 5.0 • Mai 2018: 6.0 • aktuell: 6.1.9 und 7.0.0-beta.7

Slide 12

Slide 12 text

Learnings der zwei Jahre

Slide 13

Slide 13 text

$ ng new

Slide 14

Slide 14 text

angular-cli • entwickelt vom Angular Team • standardisierte Projektstruktur inkl Tests • Production Build • Webpack • ab v6: Updates und Libraries

Slide 15

Slide 15 text

ng add $ ng add @angular/material • fügt Angular Material in die Applikation • fügt die CSS Themes hinzu • das Default Theme • alle nötigen Imports des Moduls $ ng generate @angular/material:material-nav —name=nav • erstellt eine NavComponent • erstellt den kompletten Boilerplate-Code
 


Slide 16

Slide 16 text

ng update • aktualisiert Pakte und startet Migrationsskripte (wenn verfügbar) $ ng update @angular/cli --migrate-only -- from=1.7.4 • aktualisiert von v1.7.4 auf v6.1.9 • fügt fehlende Abhängigkeiten hinzu • migriert zur neuen angular.json Datei

Slide 17

Slide 17 text

Struktur Architektur

Slide 18

Slide 18 text

Angular Architektur ngModule ngModule root Module ngModule Router Component Template Styles Service Pipe Directive imports PropertyBinding EventBinding DI

Slide 19

Slide 19 text

Architektur-Vorschlag • CoreModule • SharedModule • Feature Module • fachlich • technisch

Slide 20

Slide 20 text

CoreModule • Singleton Services • nur einmal pro Instanz • Beispiele • (Authentifizierung / User) • MediaQueries • Datum/Zeit

Slide 21

Slide 21 text

modules/ core/ services/ core.module.ts index.ts Re-Export von CoreModule

Slide 22

Slide 22 text

SharedModule • beinhaltet „einfache“ Components • Pipes • Import und Re-Export von Angular Material Komponenten

Slide 23

Slide 23 text

Feature Modules • Components • Components • Pages • Dialogs • Services • Konstanten • Models • Utilities

Slide 24

Slide 24 text

modules/ foo-bar/ components/ baz/ baz.component.html baz.component.scss baz.component.spec.ts baz.component.ts constants/ dialogs/ directives/ models/ pages/ pipes/ services/ utils/

Slide 25

Slide 25 text

Faustregeln für Feature Modules • sind fachlich gekapselt • importieren Services nur aus dem CoreModule • Lazy loaded

Slide 26

Slide 26 text

Lazy Loading AppRoutingModule Feature Module Routing Module Component

Slide 27

Slide 27 text

const routes: Routes = [ { path: 'feature', loadChildren: 'app/feature/feature.module#FeatureModule' }, { path: '', redirectTo: '', pathMatch: 'full' } ]; src/app/app-routing.module.ts

Slide 28

Slide 28 text

import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FeatureRoutingModule } from './feature-routing.module'; import { FeatureComponent } from './feature/feature.component'; @NgModule({ imports: [ CommonModule, FeatureRoutingModule ], declarations: [ FeatureComponent ] }) export class FeatureModule { } src/app/modules/feature/feature.module.ts

Slide 29

Slide 29 text

Aliase

Slide 30

Slide 30 text

@app • konsistente Importe in der kompletten App • Beispiel
 
 import { 
 FooService 
 } from '../../../core/package/foo.service'; • besser:
 
 import { FooService } from '@app/core';

Slide 31

Slide 31 text

{ "compilerOptions": { "...": "...", "baseUrl": "src", "paths": { "@app/*": ["app/*"], "@env/*": ["environments/*"] } } } tsconfig.json

Slide 32

Slide 32 text

import { Component, OnInit } from '@angular/core'; import { Observable } from 'rxjs/Observable'; import { SingletonService } from '@app/core'; import { environment } from '@env/environment'; import { ExampleService } from './example.service'; @Component({ /* ... */ }) export class ExampleComponent implements OnInit { constructor( private SingletonService: SingletonService, private exampleService: ExampleService ) {} } example.component.ts Third Party App Globals Locally

Slide 33

Slide 33 text

Typings

Slide 34

Slide 34 text

Typings interface User { firstName: string;
 lastName: string;
 age: number;
 createdDate: string | Date;
 } Response vom Server Rückgabewert eines Datepickers

Slide 35

Slide 35 text

Typ Restriktionen (I) interface Order { state: 'pending' | 'approved' | 'rejected'; }

Slide 36

Slide 36 text

Typ Restriktionen (II) enum States { pending = 1, approved = 2, rejected = 3; } interface Order { state: States; }

Slide 37

Slide 37 text

rxjs/observable

Slide 38

Slide 38 text

class CountryService { private countries: Observable; constructor(private http: Http) { this.countries = this.http.get('/api/countries') .publishReplay(1) .refCount(); } public getCountries(): Observable { return this.countries; } } country.service.ts rxjs cached den letzten Emittenten Wert. das Observable ist nutzbar, solange Subscriptions aktiv sind

Slide 39

Slide 39 text

SCSS

Slide 40

Slide 40 text

SCSS • SCSS ist ein CSS Präprozessor • Features • Variablen • Funktionen • Mixins • Angular Materials nutzt SCSS

Slide 41

Slide 41 text

Beispiel @import "config/colors"; :host { display: flex; align-items: center; max-width: px-to-rem(200); }
 
 $rem-base: 16; @function px-to-rem($px-value) { @return $px-value / $rem-base * 1rem; }

Slide 42

Slide 42 text

Testing

Slide 43

Slide 43 text

ng test • Testen von Angular Apps ist einfach
 
 $ ng test • Es wird Jasmine mit Karma und PhantomJS verwendet • Nachteile • langsam • PhantomJS hat eine veraltete Rendering Engine • PhantomJS wird nicht mehr weiter entwickelt

Slide 44

Slide 44 text

ng test • Chrome 59 und später hat einen Headless Modus • Das geht einfach
 
 $ ng test --browser ChromeHeadless --single-run • Nachteile • es ist immer noch langsam

Slide 45

Slide 45 text

Jest • „Delightful JavaScript Testing“ von Facebook • Jest ist fast API-kompatibel mit Jasmine • Fokus auf die Entwicklung (schnell und einfach zu nutzen) • abstrahiert den DOM über JSDOM • Code Coverage out of the box • TypeScript Support

Slide 46

Slide 46 text

Jest Installation $ yarn add --dev jest jest-preset-angular @types/jest

Slide 47

Slide 47 text

Vorteile von Jest • 300% schnellere Testausführung • ~2700 Tests laufen in etwa 60 Sekunden • Integration in WebStorm und VS Code • Snapshot Testing möglich

Slide 48

Slide 48 text

Commit Messages + ChangeLog Generator

Slide 49

Slide 49 text

• github.com/conventional-changelog/standard-version • definiert • Typ des Commits (Fix, Feature, Layout, usw.) • Optional den Scope (Component oder Module) • Commit Message • Optional Body • Ticket-ID

Slide 50

Slide 50 text

fix(foo-bar): removes dependency of jQuery We don’t need jQuery, so it can be removed closes #4711

Slide 51

Slide 51 text

2.0.0 (2018-06-26) Bug Fixes • FooBar: removes dependency of jQuery (8a0f5aa), closes #4711 Semantic Versioning SHA-1 Hash

Slide 52

Slide 52 text

Build

Slide 53

Slide 53 text

Development Build • $ yarn start • startet yarn serve
 
 "serve": "ng serve —sourcemaps --ssl -- host=0.0.0.0 --disable-host-check --extract-css" • startet das Testbackend mit yarn test-backend
 
 "test-backend": "nodemon --watch test-backend -e js,ts,json -i '*.spec.ts' --exec \"cd test- backend && ts-node -r tsconfig-paths/register\" src/server.ts"


Slide 54

Slide 54 text

Production Build • Unser Production Build
 
 "build:prod": "npm run version && npm run node-with-more-memory ./node_modules/ @angular/cli/bin/ng build -- --build- optimizer --env=prod"

Slide 55

Slide 55 text

Debugging mit Augury

Slide 56

Slide 56 text

Augury • Google Chrome Developer Tool Erweiterung • visualisiert Components • visuelles Debugging möglich • Change Detection und Performance Checks

Slide 57

Slide 57 text

Augury

Slide 58

Slide 58 text

Danke für eure Aufmerksamkeit!

Slide 59

Slide 59 text

Fragen?

Slide 60

Slide 60 text

[email protected] @ThorstenRinne