Teil 1
Im Spannungsfeld der Anforderungen
Nutzer möchten eine konsistente, gut bedienbare UI erleben
Axiom I
Beste UI / UX kann nur durch Single Page Applications (SPA), Mobile oder Desktop App erreicht werden
Logik muss nahe an Interaktion und Daten müssen nahe an Logik liegen
SPA
verschieben daher Hauptteile eurer Anwendung in den Client
- Server ist hauptsächlich Daten-Schnittstelle (JSON/REST API)
- Server kann Business Logic enthalten, diese kann aber komplett im Client liegen
- erlaubt Offline-Betrieb für SPAs (u.a. über Service Workers)
Größere Anwendungen können nicht von einem einzigen Team entwickelt werden
Axiom II
Wartbarkeit und Skalierung im größeren Kontext ist nur durch Modularisierung erreichbar
Moderne Frontends...
- sollen aus einzelnen Modulen zusammensetzbar sein
- müssen zu modernen Backend-Architekturen passen
- sollen einzeln zu deployen sein
- sollen pro Modul am besten die freie Wahl von Technologie erlauben
Das passende Buzzword dazu ist Micro Frontends (
https://www.thoughtworks.com/radar/techniques/micro-frontends
)
Spannung zwischen Axiom I und II
Wenn man die Module für Wartbarkeit entkoppelt (Micro Frontends) muss man sie für ein UI aus einem Guss wieder koppeln
Oder: man muss sich entscheiden, will man:
- die beste Erfahrung für den Nutzer oder
- den besten Entwicklungsprozess
Es gibt keinen besten Architektur-Ansatz
Daher...
Man muss die Anforderungen kennen und die müssen passen.
- Oliver Zeigermann, embarc
Typische Ziele/Einflüsse
- Entwicklungsgeschwindigkeit
- Robustheit
- Risko-Minimierung
- Skalierbarkeit der Entwicklung
- UX, Konsistenz
UX, Konsistenz
- Gleichzeitige, synchronisierte Darstellung mehrerer Module
- Schnelle erste Darstellung
- Offline-Fähigkeit
- Unverzögerte Reaktion
Risko-Minimierung
- schrittweises Ausrollen von technischen Innovationen
- schrittweise Migration, kein Big Bang
- Feature-Stau
Skalierbarkeit der Entwicklung / Entwicklungsgeschwindigkeit
- Anzahl der Teams
- Freie Wahl des Frameworks
- Update der Bibliotheken
- Eignung für vertikale Architektur
- Gemeinsame Bibliothek, Wiederverwendung
- Freiheitsgrad der Modulgröße
- Migrationspfad von klassischer Web-App
Übung #1
Unterhalte dich mit deinen Sitznachbarn über dein eigenes (oder ein dir bekanntes) Frontend
Welche Anforderungen gibt es in dem Projekt?
Wie begegnet ihr diesen?
Wir nehmen Frontend-Architektur nicht für voll
Zitate
- Frontend-Architektur: Ich dachte sowas gibt es gar nicht
- Das Frontend kloppen wir am Ende einfach irgendwie drauf
- Architektur für ein bisschen CSS-Pixel-Geschubse?
Micro Frontend Architektur-Ansätze
Integration...
- über Links - Codename Links
- zur Build-Zeit - Codename
Majestic Modular Monoliths
(Kudos an @axelfontaine für den Namen)
- im Browser - Codename Micro Components
Ansatz 1: Größte Unabhängigkeit
Eigenständige Anwendungen über Links verbunden
Integration mehrerer Anwendungen über Links, die eine neue Anwendung öffnen und/oder die alte ersetzen
- jedes Modul ist eine eigene (SPA) Anwendung
- erlaubt Vertikalen wie eine klassische Web-App
- Module teilen keinen Zustand, aktualisieren einander nicht
Links
Variante: App Shell hat JavaScript Rahmen, weniger flexibel, kann aber u.a. Zusand halten
Eigenständige Anwendungen in Eigenständiger Darstellung
Jede Anwendung wird komplett neu aufgebaut
Prominentes Beispiel: Outlook Online
UX-Schwächen, unterschiedliche Technologien, jede App wird anders dargestellt
Wechsel der App dauert (Service Workers können die Zeit ab 2. Aufruf vermindern)
Technik
Kommunikation zwischen getrennten Anwendungen
Ansätze: Links
Bedient Anforderungen: nicht gleichzeitige, aber synchronisierte Darstellung mehrerer Module
Real-Time
- Long Polling: Erfordert Server Verbindung, kann viel Server Resourcen fressen
- Web Sockets: Erfordert Server Verbindung, geht immer noch nicht überall
- PWA Push: Erfordert Service Worker und Server
Parameter-Übergabe
- Cookies: gut für Session Id, Tokens
- URL Parameter: begrenzte Länge, nicht alles möchte man in der URL haben, Bookmark und verschickbarer Link möglich
- Session Storage: Key/Value, wird gelöscht wenn Tab geschlossen wird
- Local Storage: Key/Value, bleibt bestehen bis zur expliziten Löschung
Alle Änsätze halten auch bei Reload den Zustand
Ansatz 2: Bestes UX
Single Page Application
Eine einzelne Single Page Application mit statischem Build
- Jedes Team entwickelt eigenes Modul
- Statischer Build integriert komplette Anwendung
- Zur Laufzeit Lazy-Loading möglich
- Anwendung nutzt ein Framework mit einer Version
- Gemeinsame Bibliothek sinnvoll
- Export einzelner Komponenten möglich
Majestic Modular Monoliths
Gemeinsame Anwendungen in gemeinsamer Darstellung
Server-Zugriff nur für Daten oder einmalig für Code
Prominentes Beispiel: Google Docs
Keine systematischen UX Probleme
Ansatz 3: Mittelweg
Zusammensetzen der Anwendung im Browser
- Anwendung ist in logische Module aufgeteilt, die als ganze Anwendung zusammen laufen
- Frameworks frei wählbar pro Modul
- Gesamtanwendung wahrscheinlich groß
Micro Components
Eigenständige Anwendungen in gemeinsamer Darstellung
Jede Anwendung kann komplett eigenen Stack haben
Kommunikation über EventBus, direkte Listener oder gemeinsamer Zustand
überraschende UX Schwächen, Apps nur gleichzeitig dargestellt, aber nicht komplett integriert
Technik
Client-Seitige Integration
Ansätze: Micro Components
Bedient Anforderungen: Gleichzeitige, synchronisierte Darstellung mehrerer Module
- einfache script Tags und unterschiedliche Mount Points (z.B. http://www.sport1.de/fussball/bundesliga/live-ticker)
- Web Components
- iFrames
Web Components
Web Component ummantelt Modul
Beispiel:
import 'my-element';
<my-element greeting="Hello"></my-element>
class MyElement extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.greeting = this.getAttribute("greeting") || 'Hello';
}
connectedCallback() {
render(); // whatever framework
this.btn = this.shadowRoot.querySelector('button');
this.btn.addEventListener('click', (event) => ...);
}
}
customElements.define('my-element', MyElement);
Keine Komplette Isolation, Funktioniert in der Praxis nicht gut mit beliebigem Framework
iFrame
Beispiel: http://djcordhose.github.io/architecture/code/integration/
Lädt komplett isolierte Anwendung
<iframe height="300" width="500"
src="http://djcordhose.github.io/architecture/code/integration/iframe.html"
sandbox="allow-scripts allow-top-navigation allow-same-origin"></iframe>
- Kein geteiltes Styling
- Einbetten mit richtiger Größe ein Albtraum
- Kommunikation mit Außenwelt lästig
Problem: Ladezeiten, wenn jedes Modul sein eigenes Framework mitbringt
- Frameworks wie React oder Angular bringen von sich aus immer mehr als 100KB mit
- (UI-)Bibliotheken haben oft dieselbe Größe oder mehr
- Bei mehreren Modulen ist man schnell im MB-Bereich: Langsamer Aufbau der Seite
Lösung: k(l)eine Frameworks und Bibliotheken nutzen
- Preact kann Anwendungen unter 10KB bringen
- Web-Components sind Teil der Browser API (noch nicht überall)
Ansätze sind nicht wechselseitig exklusiv
- Seite einer Link-App kann eine Micro Components App sein
- Teil einer Micro Components kann ein Majestic Modular Monolith sein
- Seite einer Link-App kann ein Majestic Modular Monolith sein (Google Drive vs Google Docs)
Übung #2
- Welche Ansätze findest du in dieser Anwendung?
- Welche Anforderungen (auch an den Entwicklungsprozess) hat es wohl gegeben?
- Welchen Ansatz hättest du gewählt?
Mobile Seitenansichten
Profile - Contacts - Messenger
Urteil
- Links: bester Entwicklungsprozess
- beste Story für Modularisierung, Migration, Deployment
- schwächste Integration von UI/UX
- Majestic Modular Monoliths: beste Erfahrung für den Nutzer
- schwächste Story für unabhängige Teams
- bestes und konsistentestes UX/UI, starke Stories für State Management und Universal Web Apps
- Micro Components: Kompromiss
- migration von Klassischer Wep-App schwer denkbar
- UX/UI gut für Intranet oder Desktop
Empfehlung
Anwendung komplett trennen und mit Links verbinden wo möglich
Wahrscheinlich sind mehr Trennungen möglich als ihr denkt
Getrennte Anwendungen als
Majestic Modular Monoliths außer wenn starke Anforderung an Unabhängigkeit