Welches Webframework passt zu mir? (WJAX)

Preview:

Citation preview

Welche Webtechnologie passt zu mir?

Alexander Casall@sialcasa

Software Architekt &Scrum Product Owner

Webentwicklung

DAS richtige Webframework

Webframeworks

https://github.com/mraible/history-of-web-frameworks-timeline

Server-seitiges Rendering vs

Client-seitiges Rendering aka Single Page Applications (SPA)

Rendering

Rendering

Server

Client

Server side rendering

Client siderendering

GET http://catcontent.com

RenderingServer

Client

GET

<html> … </html>

GET<html> … </html>

GET<html> … </html>

Server Side Rendering

Rendering

Rendering

Server

Client

Server side rendering

Client siderendering

GET http://catcontent.com

Rendering

Server

Client

GET

<html> <script> </script> </html>

GET

{ "cat": { "name":"grumpy“ } }

GET

{ "cat": { "name":"garfield“ } }

Client Side Rendering

Vorteile• Caching der

gerenderten Templates • Dokumenten-Ansatz

• Hohe User Experience • Ein Programmiermodell

im Client (klare Trennung der Aspekte)

RenderingServer

Client

Rendering

Server

Client

Nachteile• Seiten müssen erneut

übertragen werden • Serverseitige Sessions

notwendig (stateful)

• Initialer Ladeaufwand • SEO kritischer • Zusätzliche API

Schicht (e.g. REST) • Unvorhersehbare

Performance

RenderingServer

Client

Rendering

Server

Client

Single Page Applications

https://github.com/mraible/history-of-web-frameworks-timeline

SPAs

Angular 2 vs. React

als Rich Client Platform zu verstehen

in TypeScript geschriebenes SPA Framework

verfolgt Komponentenansatz

Angular

Typescript

Optional statisch getypt interfaces, enums, generics, access modifiers …

interface ICar{ engine: string; color: string; }

class Car implements ICar {

constructor (public engine: string, public color: string) {}

private drive(direction:Direction) : boolean{ return false; //unfall }

}

Transpiliert zu JavaScript

Komponenten

Komponentenansatzheader component

category component

discount component

content component

suggestionsoverview component

suggestion component

webshop component

highlight component

@Component({ selector: 'category', templateUrl: 'category.component.html', styleUrls: ['category.component.css'], }) export class CategoryComponent { title = 'categorycomponent works!'; }

Struktur einer Komponente

@Component({ selector: 'categories', template: '<h1> {{title}} </h1>', styleUrls: ['category.component.css'], }) export class CategoryComponent { title = 'categorycomponent works!'; }

Template

Styles

TypeScript

Struktur einer Komponente

Ein genauerer Blick auf Templates

@Component({ selector: 'categories', template: `<ul>

<li *ngFor="let category of categories"> {{category.name}} </li> </ul>`,

styleUrls: ['category.component.css'], }) export class CategoryComponent {

var categories: Categories[] = [ { "id": 1, "name": "jackets" }, { "id": 2, "name": "trousers" }, { "id": 3, "name": "planes" } ];

}

Structural Directive

<— Binding

@Component({ selector: 'categories',

template: '<button [style.color] = "cool ? 'red': 'green'" (click)="toggleCoolness()">Coolness</button>'

}) export class CategoryComponent {

cool = false;

switchCoolness(){ this.cool = !this.cool;

}

}

Style Bindings

Unidirektionales Binding@Component({ selector: 'categories', template: `<h1> {{title}} </h1>`, styleUrls: ['category.component.css'], }) export class CategoryComponent { title = 'Display this!'; }

Bidirektionales Binding & Events

@Component({ selector: 'categories', template: '<input [(ngModel)]="input"

(click)="addPlus()">' styleUrls: ['category.component.css'], }) export class CategoryComponent {

input = 'initial Value';

addPlus(){ title += '+';

}

}

https://angular.io/docs/ts/latest/guide/template-syntax.html#!#binding-syntax

Verschachtelung

@Component({ selector: 'webshop', template: `

<header/> <categories/> <discounts/> <content/> <suggestions/> `

}) export class WebshopComponent {

}

Verschachtelung der Komponenten

Komponentenansatzheader component

category component

webshop component

@Component({ selector: 'webshop', template: `

<header/> <categories/> <discounts/> <content/> <suggestions/> `

}) export class WebshopComponent {

}

@Component({ selector: 'categories', templateUrl: 'category.component.html' }) export class CategoryComponent { }

Komponentenansatzheader component

category component

webshop component

Kommunikation zwischen Parent / Child?

@Component({ selector: 'parent',

template: '<child [text]="displayInChild"></child>' }) export class ParentComponent {

displayInChild = 'Text of Parent!' }

Daten von Parent zu Child über Binding

@Component({ selector: 'child',

template: '<label>{{text}}</label>'‚ }) export class ChildComponent {

@Input() text : String }

@Component({ selector: 'parent', template: '<child (close)="onEvent($event)"> </child>' }) export class ParentComponent {

onEvent(input: String) {…} }

Daten von Child zu Parent über Events

@Component({ selector: 'child',

template: '<label (click)="close.emit('closeme')">Text</label>'‚ }) export class ChildComponent {

@Output() close : EventEmitter<String>

}

Weitere Kommunikationsarten zwischen Parent / Child möglich

https://angular.io/docs/ts/latest/cookbook/component-communication.html

Services für Datenzugriffe

Services

@Injectable() export class CategoryService { getCategories() : Category[]{ … } }

Component

Service

Dependency Injection

CategoryService

CompA

@Component({ …, providers:[CategoryService] }) export class CompA {}

CompB CompC

@Component({…}) export class CompB {

//Constructor Injection constructor (private _service:

CategoryService){}

doSomeThing(){ this._service.getCategories(); } }

CompC sieht genau so aus, und bekommt die gleiche Instanz des Services

CategoryService

CompA

CompB CompC

@Component({ providers:[CategoryService], … }) export class CompB {

//Constructor Injection constructor (private _service:

CategoryService){}

doSomeThing(){ this._service.getCategories(); } }

CompC sieht genau so aus, und bekommt die eine eigene Instanz des Services

CategoryService

React

• SPA Library

• verfolgt Komponenten Ansatz

• beschränkt sich im Kern auf Strukturierung und Rendering von Komponenten

React

Struktur einer Komponente

class HelloWorldItem extends React.Component{ constructor(props){ super(props); this.state.counter = 1;

}

render(){ return React.createElement('div', {}, React.createElement('label', ...), ); } }

Struktur einer Komponente

class HelloWorldItem extends React.Component{ constructor(props){ super(props); this.state.counter = 1;

}

render(){ return ( <div>

<label>{this.props.title}</label> </div>

) } }

JSX

class HelloWorldItem extends React.Component{ constructor(props){ super(props); this.state.counter = 1;

}

render(){ return ( <div>

<label>{this.props.title}</label> </div>

) } }

Struktur einer Komponente

Input von parent

Interner Zustand

Render wird aufgerufen, wenn props oder state neu gesetzt wird

Ein genauerer Blick auf JSX

class HelloWorldList extends React.Component{

constructor(props){ super(props); }

render(){ return ( <div> <ul> {this.props.items.map((i,index) => <li key={index}>{i}</li> )} </ul> </div> ) } }}

JavaScript statt Template Syntax

class MyComponent extends React.Component { constructor(props) { super(props); this.onInputChanged = onInputChanged.bind(this);

}

onInputChanged(event) { this.setState({input: event.target.value});

}

render() { return ( <div> <input type="text" value={this.state.input} onChange={this.onInputChanged}/>

</div> );

} }

Eventhandling

class MyComponent extends React.Component { render() { var header = <h1>MyHeader</h1>; var footer = <p>Footer 2016</p>; var greeting;

if(this.props.loggedIn) { greeting = <p>Hallo {this.props.name}</p>;

} else { greeting = <p>Hallo Gast</p>;

}

return ( <div> {header} {greeting} {footer}

</div> );

} }

JSX in erweiterter Ausprägung

Render wird aufgerufen, wenn props oder state neu gesetzt wird

Verschachtelung

Verschachtelung der Komponenten

class Webshop extends React.Component{ constructor(props){ super(props); } render() { return (

<div> <Header/> <Categories/> <Discounts/> <Content/> <Suggestions/> </div>

); } }

class Webshop extends React.Component{ constructor(props){ super(props); } render() { return (

<div> <Header/> <Categories/> <Discounts/> <Content/> <Suggestions/> </div>

); } }

class Categories extends React.Component

Kommunikation zwischen Parent / Child?

class Parent extends React.Component{ … render() { return (

<div> <Child items={this.state.items}/> </div>

); }}

class Child extends React.Component{ render() { return ({

this.props.items.map((i,index) => <div>{i}</div>

) }); }}

Daten von Parent zu Child über Props

class Parent extends React.Component{ … render() { return (

<div> <Child someAction={this.callBack.bind(this)}/> </div>

);}

callBack(){//Do something} }

class Child extends React.Component{ render() { return (

<div> <input type="button" onClick={this.props.someAction}/>

</div> ); }}

Callback Funktionen von Child zu Parent

Wie sieht die Architektur abseits der Komponenten aus?

(äquivalent Services, DI)

Redux

Component

Actions

Reducer

Reducer

Reducer

State

Middleware

(state, action) => state

Bekannte Konzepte Teilweise uneindeutiger Datenfluss

Neue Konzepte Eindeutiger Datenfluss

ABER

Es existiert ein Redux Binding für Angular 2

Kurzes Resümee

Was React (nicht) ist

• Reacts Hauptanspruch ist die Strukturierung der Anwendung

• React ist eine sehr gute Rendering-Bibliothek

• React ist keine Rich Client Platform

• React ist keine Komponenten Bibliothek

Was Angular (nicht) ist

• Angulars Hauptanspruch ist die Strukturierung der Anwendung

• Angular ist eine Rich Client Platform

• Angular ist keine Komponenten Bibliothek

Welche Unterschiede existieren?

• React setzt auf JSX

• Angular setzt auf Templates (Lernaufwand)

• Angular bietet Uni - und Bidirektionales Binding

• React nutzt render() wenn State / Props neu gesetzt wird

• React eher funktional, Angular eher OOP

Anwendungen gehen über den Komponentenansatz hinaus

AnwendungsentwicklungLifecycle Hooks für Komponenten

Backend-Anbindung Dependency Injection Access-Management

Formular-Handling & (Async)-Validation Accessibility

Security Controls Routing

i18n Mobile

Komplexes Focus Management UI Tests

Lifecycle Hooks für Komponenten

Backend-Anbindung

Dependency Injection

Access-Management

Formular-Handling & (Async)-Validation

Accessibility

KernfunktionDrittanbieterNicht vorhanden

Security

Controls

Routing

i18n

Mobile

Komplexes Focus Management

UI Tests

KernfunktionDrittanbieterNicht vorhanden

Beispiel Routing

Routing

Routing

Routing @ Angular

const contentRoutes:RouterConfig =[{

path:‘highlight',component:HighlightComponent},

{path:’catalogue',component:CatalogueComponent,]}

];

export const appRouterProviders =[provideRouter(routes)];

Routing deklarieren

@Component({ selector: 'content', template: `

<a routerLink="/highlight">Highlights</a> <a routerLink="/catalogue">Katalog</a>

<router-outlet></router-outlet>

` }) export class ContentComponent {}

Routing

Routing @ React via 3rd Party lib

https://github.com/ReactTraining/react-router

Routing deklarieren

render(( <Router history={browserHistory}> <Route path="/" component={App}> <Route path="about" component={About}/> <Route path="users" component={Users}> <Route path="/user/:userId" component={User}/> </Route> <Route path="*" component={NoMatch}/> </Route> </Router> ), document.getElementById('root'))

Routing nutzen

const Users = React.createClass({ render() { return (

<div> <Link to={`/user/${user.id}`}>{user.name}</Link>

</div> ) } })

= =Routing Routing

Kurzes Resümee

React (Stack) Angular 2

Ok, genug Funktionen - was ist mit Zukunftssicherheit?

Zukunftssicherheit

• Welche Aspekte sind wichtig?

• Stand im Produktlebenszyklus

• Strategie des Vendors

• Marktsituation

Produktlebenszyklus

Einführung

ReifeWachstum Degeneration

Hinweis

Man sollte bedenken, dass jede Third-Party Library wieder auf Ihr Zukunftssicherheit zu prüfen ist.

Wie setzt der Vendor die Bibliotheken ein

Wie setzt Google ein?

• Google Adwords (in Entwicklung)

• GreenTea (Googles internes CRM)

• Google Fiber (https://fiber.google.com/about/)

Wie setzt Facebook ein?

• in Facebook (z.B. Chat, Kommentare)

• WhatsApp Webapp

• Instagram

Release Politik /Versionierung

Release Strategie Angular

SemVer

http://angularjs.blogspot.de/2016/10/versioning-and-releasing-angular.html?m=1&utm_campaign=NG-Newsletter&utm_medium=email&utm_source=NG-Newsletter_169

Versioning React

https://facebook.github.io/react/blog/2016/02/19/new-versioning-scheme.html

SemVer seit 0.14.7. —> 15.0.0ohne expliziten Releasezyklus

Marktsituation

Freelancer auf Gulp

0

125

250

375

500

Freelancer auf GULP

442

2030

react angular2 angular

Projekte auf Gulp

0

12,5

25

37,5

50

Projekte auf Gulp

47

33

react angular2 angular

Community auf Stackoverflow

0

2250

4500

6750

9000

Stackoverflow created:1m

8.476

6.736

3.999

react angular2 angular

Kurzes Resümee

Resümee Marktsituation

• Beide Technologien ermöglichen die Entwicklung komplexer Anwendungen

• React ist eine Bibliothek

• Angular 2 ist ein Framework (RCP)

Resümee Marktsituation

• Versioning gleich

• Angular hat transparente Releasezyklen

• Marktsituation rund um Angular etwas besser

Welche Entscheidung haben wir getroffen?

Wie sind wir bei unserer Entscheidung vorgegangen?

Beide Technologien sind relevant und wir sollten uns

mit ihnen auskennen.

Wenn Greenfield Projekt, dann Angular

MERKE

Wer Webanwendungen baut muss lernen permanent zu lernen.

Danketwitter.com/sialcasa

Umsetzung von Software, Beratung und Training

https://www.similartech.com/compare/angular-js-vs-react-js

Why Do People Hate Client-Side JavaScript?Everyone is different, and if you asked 100 different haters I’m

sure they would have 100 different flavors of Hatorade™.

https://webmasters.googleblog.com/2014/05/understanding-web-pages-better.html

export default class Counter extends Component { constructor(props) { super(props); }

render() { const { counter, increment, decrement, addTreatments } = this.props;

return ( <View style={{flex: 1, alignItems: 'center', justifyContent: 'center' }}> <Text>{counter}</Text> <TouchableOpacity onPress={decrement} style={styles.button}>

<Text>down</Text> </TouchableOpacity>

<TouchableOpacity onPress={addTreatments} style={styles.button}> <Text>Load</Text> </TouchableOpacity> </View> ); } }

React Native

@Component({ selector: 'list-test', template: ` <GridLayout rows="*"> <ListView [items]="items"> <template let-item="item"> <item-component [data]="item"></item-component> </template> </ListView> </GridLayout> ` }) export class ListTest {

items : Array<String>

constructor(private restClient : RestClient) { restClient.loadTreatments().subscribe(resp => console.log(resp)) //this.items =

} }

Nativescript

Recommended