Die erste Webseite der Welt, die am 20. Dezember 1990 am Kernforschungszentrum CERN Genf online ging, war eine einfache statische HTML-Seite mit wenigen Zeilen Code, 165 Wörter Text und einigen Hyperlinks.
Heute stehen die wichtigsten Seiten im Web für hochdynamische und interaktive Client-Server-Anwendungen mit tausenden Zeilen Code, basierend auf komplexen Frameworks. Was macht eine moderne Webanwendung aus? Warum sind moderne Webanwendungen wichtig und Wie werden sie erstellt? – Eine Einordnung der wichtigsten Begriffe, Fakten und aktuellen Trends.
Was: Moderne Webanwendungen?
Moderne Webanwendungen präsentieren sich als ausgeklügelte, oft personalisierte Single-Page-Webseiten. Der Benutzer ruft sie unkompliziert im Webbrowser seines Gerätes (PC, Smartphone, Tablet) auf. Aus technischer Sicht sind moderne Webanwendungen datenzentrierte Client-Server Systeme auf Basis von Standard-Webprotokollen.
Single-Page-Webseiten: Daten im Hintergrund unterwegs
Eine im Webbrowser ablaufende Single-Page-Webseite (single-page application, SPA) wird von vielen Benutzern irrtümlicherweise bereits als die „Anwendung“ verstanden.
Tatsächlich stellen Webseiten selbst aber nur einen kleinen und – für sich allein betrachtet – kaum nutzbaren Teil moderner Webanwendungen dar, da sie keine Daten speichern. Die „fehlenden“ Daten holen sich die Webseiten anlass- und nutzerbezogen von einem zentralen, für den Benutzer unsichtbaren Backend-Server ab. Die Webseiten erfassen während der Nutzung neue Daten vom Benutzer und spielen die erfassten Datensätze laufend an den zugehörigen Server zurück. Erst mit dem dynamischen Datenaustausch zwischen der Single-Page-Webseite – dem „Frontend“ im Browser des Benutzers – und dem Backend-Server wird die auf der Webseite implementierte Darstellungslogik mit Inhalten gefüllt, und es ergibt sich der Nutzen der Gesamtanwendung.
Anders als bei statischen Webseiten findet der Datentransfer zwischen Webseite und Server bei einer modernen Webanwendung immer im Hintergrund statt. Hierfür muss vom Benutzer kein Aktualisierungsbutton gedrückt werden, kein Reload einer Seite angestoßen werden und auch kein Seitenwechsel ausgelöst werden, wie dies noch bei herkömmlichen Webanwendungen der Fall ist. Der Datenfluss erfolgt vielmehr fortlaufend automatisch in beide Richtungen und während der gesamten Dauer der Nutzung der Webseite, flexibel angepasst an die Notwendigkeiten der jeweiligen Anwendung. Nachteil dabei: Für den Benutzer bleibt weitgehend intransparent, wann und welche Informationen bei der Nutzung erfasst und an den Server zurückgesendet werden.
Die schnelle, zuverlässige und sichere Datenkommunikation zwischen Frontend und Backend ist jedenfalls eine unabdingbare technische Voraussetzung für das Funktionieren einer modernen Webanwendung.
Leistungsfähige und intelligente Backends mit Konfliktpotenzial zur DSGVO
Für moderne Webanwendungen mit einer großen Anzahl an Benutzern und einem umfangreichen Datenaustausch werden leistungsfähige und skalierbare Backend-Lösungen benötigt.
Sie zeichnen sich gegenüber herkömmlichen Webservern dadurch aus, dass sie Inhalte (Daten) anlassbezogen generieren und bereitstellen, wo bei einfachen Webanwendungen noch lediglich fertige HTML-Seiten ausgeliefert wurden.
Insbesondere können die Backends moderner Webanwendungen Daten auch benutzerspezifisch aufbereitet zur Verfügung stellen und eingehende Informationen benutzerspezifisch verarbeiten.
Hieraus ergibt sich zwangsläufig, dass in den Backends mehr oder weniger umfangreiche Informationen zu den einzelnen Benutzern aufgezeichnet werden resp. detaillierte personenbezogene Benutzerprofile vorliegen (müssen). Damit stehen die Bedarfe der Ersteller und Betreiber moderner Webanwendungen potenziell in Konflikt mit der EU-Datenschutz-Grundverordnung (DSGVO), die die Sammlung, Speicherung und Verarbeitung personenbezogener Daten bewusst einschränkt. Die Vorgaben der DSGVO sind jedenfalls bereits beim Design dieser Anwendungen zu beachten:
- jede Erhebung personenbezogener Daten hat zweckbestimmt zu erfolgen. Sie ist generell nur dann erlaubt, wenn ein berechtigtes Interesse für die Erhebung vorliegt, und sie muss sich auf das für den konkreten Zweck notwendige Maß beschränken.
- die Speicherung der Daten ist auf den für den konkreten Zweck notwendigen Zeitraum zu beschränken, anschließend müssen die Daten gelöscht werden. Darüber hinaus hat jede betroffene Person jederzeit das Recht, das Löschen der eigenen Daten explizit zu veranlassen (Recht auf Vergessen)
- Datenspeicherung und -verarbeitung müssen unter Berücksichtigung der Gewährleistung der Privatsphäre resp. des Datenschutzes nach aktuellen Standards erfolgen. Datenspeicherung und -verarbeitung müssen transparent und nachvollziehbar sein.
Frontend und Backend als funktionale Einheit, aber nur lose gekoppelt
Clients und Server – also: Frontend und Backend – stellen bei einer modernen Webanwendung eine funktionelle Einheit mit klarer Rollenverteilung dar. Das Frontend bietet eine moderne, dem jeweiligen Zielgerät und der jeweiligen Anwendungsdomäne angepasste Benutzeroberfläche. Der zentrale „Backend“-Server implementiert die Geschäftslogik und Datenpersistenz. Über eine Datenschnittstelle sind beide, Frontend und Backend, lose miteinander gekoppelt.
Diese Frontend-Backend-Beziehung ist jedoch keinesfalls immer eine einfache 1:1 Beziehung.
So kann ein einziges Backend gleichzeitig unterschiedliche Frontend-Anwendungen (Webseiten, mobile Apps, Desktop-Apps, IoT-Geräte) mit Daten versorgen resp. von diesen Daten empfangen.
Ein bestimmtes Frontend wiederum kann Daten von mehreren Backend-Servern empfangen oder Daten an unterschiedliche Backend-Server übermitteln. Die Kommunikation mit dritten Backends (externe Dienste) dient dabei insbesondere der Implementierung allgemeiner Funktionen, wie Benutzerauthentifizierung, Rate Limiting, Fakturierung sowie Analyse und Überwachung.
Dass der (bequeme) Zugriff von Frontends auf externe Backends unter Umständen aber nicht unkritisch ist, zeigt das Urteil des Landgerichts München vom 20.01.2022, wonach die dynamische Einbindung der (beliebten) Google Fonts auf Webseiten ohne vorherige Einwilligung des Benutzers bereits einen Verstoß gegenüber der europäischen DSGVO darstellt und auch als solcher geahndet werden kann, da im Zuge der dynamischen Einbindung die IP-Adresse des Nutzers an Google (und damit in einen „unsicheren Drittstaat“) übermittelt wird.
Warum: Moderne Webanwendungen?
Moderne Webanwendungen kombinieren die allgemeinen Vorteile herkömmlicher Webanwendungen mit Vorteilen, die sich spezifisch aus dem flexiblen und schnellen Datenaustausch zwischen Frontend und Backend und der Personalisierung von Webseiten ergeben.
Ein allgemeiner Vorteil aller Webanwendungen ist, dass sie keine lokale Software-Installation auf den Benutzergeräten erfordern, da die Backendfunktionalität auf einen zentralen Server ausgelagert wird und das Frontend im ohnehin auf dem Gerät bereits installierten Webbrowsers abläuft – idealerweise bei allen aktuellen Web-Browsern mit gleichen Funktionsumfang und (fast) identischer Darstellung. Dadurch, dass es keine lokalen Softwareinstallationen gibt, entfällt zudem die Notwendigkeit von etwaigen Software-Updates. In Summe ist die Bereitstellung der Anwendung deutlich einfacher als bei Desktop-Anwendungen, insbesondere bei einer großen Anzahl von (potenziellen) Nutzern.
Lange Zeit wurde dieser Vorteil mit dem Nachteil eines eingeschränkten Funktionsumfanges im Vergleich zu Desktop-Anwendungen erkauft. Heutige Browser resp. heutige moderne Webanwendungen bieten dem Benutzer dagegen mit HTML5 komfortable Bedienschnittstellen, die kaum noch Wünsche offenlassen. Hierzu trägt auch wesentlich der Umstand bei, dass der umfangreiche Datentransfer zwischen Frontend und Backend bei einer modernen Webanwendung im Hintergrund erfolgt, so dass das Nutzererlebnis nicht durch Seiten-Reloads oder Seitenwechsel beeinträchtigt wird.
Ein zweiter allgemeiner Vorteil aller Webanwendungen ist, dass sie per se für einen Mehrbenutzerbetrieb ausgelegt sind – wiederum ein signifikanter Vorteil gegenüber Desktop-Anwendungen. Die Mehrbenutzerfähigkeit einer Webanwendung wird prinzipiell nur durch die Leistungsfähigkeit des zugehörigen Backends und dessen Internetanbindung eingeschränkt – beides lässt sich skalieren.
Der eigentliche spezifische Vorteil moderner Webanwendungen aber ist der dynamische und flexible Datenfluss zwischen Frontend und Backend, der jederzeit in beide Richtungen möglich ist.
Basierend auf diesem Mechanismus können aktuelle Informationen ereignisgesteuert „in Echtzeit“ vom Backend an das Frontend übermittelt und dort dem Benutzer dargestellt werden. Beispiele solcher „Echtzeitinformationen“ sind die sich fortlaufend ändernden Positionen von fahrenden Fahrzeugen, Statusinformationen von Geräten und/oder anderen Benutzern, Nachrichten und Kommentaren anderer Benutzer (Chatfunktion/Umfragefunktionen), Warnungen und Störmeldungen, Spielzüge von Mitspielern usw. Häufig stammen die übermittelten Informationen von anderen Clients derselben Webanwendung, so dass aus Sicht der Benutzer eine direkte Client-Client-Kommunikation gegeben scheint. Umgekehrt sind durch die unmittelbare Übertragung eingegebener Daten / Aktivitäten des Benutzers an den Backendserver diese Informationen in kürzester Zeit für andere Benutzer verfügbar.
Mit dieser „Echtzeitkommunikation“ in beide Richtungen lassen sich komplexe Anwendungen wie Messenger, Leitsysteme, IoT-Dashboards, Mehrbenutzer-Editoren (mit kontinuierlicher automatischer Speicherung des jeweiligen Arbeitstandes) und Mehrbenutzer-Onlinespiele effizient als Webanwendungen implementieren, die zuvor höchstens als native Anwendungen denkbar gewesen wären. Zu den modernen Webanwendungen gehören nicht zuletzt aber auch Anwendungen, die es in dieser Form zuvor noch gar nicht gegeben hat, wie Echtzeitumfrage-Tools für Konferenzen/Schulungen.
Bildhaft gesprochen, werden mit modernen Webanwendungen Werkzeuge zur Verfügung gestellt, mit denen Benutzer etwas „tun“ können, während statische Webseiten im Wesentlichen dafür geeignet waren, Dinge „anzuschauen“.
Wie: Moderne Webanwendungen?
Moderne Webanwendungen bestehen aus Frontend- und Backend-Softwarekomponenten, die über eine leistungsfähige Datenschnittstelle auf Basis von Standard-Webprotokollen lose gekoppelt sind.
Die Front- und Backend-Softwarekomponenten können unabhängig voneinander entwickelt und in unterschiedlichen Sprachen resp. mit unterschiedlichen Frameworks implementiert als auch unabhängig voneinander getestet werden – ggf. auch in unterschiedlichen Teams, räumlich und zeitlich voneinander getrennt. Voraussetzung hierfür ist das Vorliegen eines ausreichend detaillierten und schlüssigen Gesamtkonzepts, basierend auf klaren Gesamtsystem-Anforderungen.
Mitunter wird umgekehrt jedoch bewusst eine enge Verschränkung von Front- und Backendentwicklung angestrebt. Die Notwendigkeit ergibt sich z.B. dann, wenn serverseitiges HTML-Rendering (traditionelles Verfahren) und clientseitiges HTML-Rendering (modernes Verfahren) gemischt werden – ein Ansatz, der aus mehrschichtigen Gründen (Performance, Security, Verfügbarkeit) wieder en vogue ist. Technisch wird die Verschränkung von Front- und Backendentwicklung z.B. durch den Einsatz eines Nx-Monorepos unterstützt.
Der Prozess der Erstellung moderner Webanwendungen wird allgemein als Webentwicklung bezeichnet. Liegt die Verantwortung für die Implementierung und den Betrieb der Anwendung (resp. einer bestimmten Komponente der Anwendung) gemeinsam in einem Team, wird von einem DevOps-Ansatz gesprochen.
Backend-Entwicklung und Backend-Architektur
Backends für Webanwendungen wurden ursprünglich in Java oder .Net, z.T. auch in PHP entwickelt. Das erste moderne Web2.0-Application-Framework war Ruby on Rails (ab 2005), welches die Webentwicklung nachhaltig verändert hat.
Heute findet das schnelle und leistungsfähige Node.js (ab 2009) eine immer größere Verbreitung bei der Implementierung von Backend-Servern. Für Node.js sind zahlreiche Frameworks und Bibliotheken verfügbar. Als zentraler Vorteil von Node.js gilt, dass Backend und Frontend in der gleichen Programmiersprache entwickelt werden (JavaScript/TypeScript) und dass Node.js Anwendungen in der Regel ohne einen zusätzlichen Webserver auskommen.
Eine bei Entwicklern beliebte, jedoch weit weniger verbreitete Alterative zu Node.js ist das in Elixier (ab 2014, Erlang-VM) geschriebene, an Ruby on Rails orientierte Phoenix/LiveView Framework (ab 2015), welches ein serverseitiges MVC-Muster implementiert. Phoenix Anwendungen werden im Erlang-Webserver Cowboy bereitgestellt.
Architektur
Die Skalierbarkeit von Backends wird u.a. mit einer Microservice-Architektur erreicht. Hierbei wird das das Backend in Form von kleinen, monofunktionalen Modulen (den Microservices) implementiert, die – ähnlich dem SOA-Ansatz – unabhängig voneinander entwickelt und ausgeliefert werden können. Ein Mikroservice, der unter höherer Last steht, kann unabhängig von den anderen Diensten skaliert werden, indem zusätzliche Instanzen dieses Dienstes (temporär) in die Anwendung integriert werden. Dies funktioniert jedoch nur, wenn die einzelnen Services wirklich unabhängig voneinander konzipiert sind, inkl. voneinander unabhängiger Datenbankinstanzen. Den Vorteilen einer Microservice-Architektur steht der höhere Overhead im Vergleich zu einer monolithischen Lösung gegenüber.
Für die Frontend-Clients sollen die Mikroservices des Backends in der Regel nur indirekt über API-Gateways erreichbar sein. API-Gateways sind Reverse Proxys, die als zentraler Zugangspunkt alle API-Aufrufe der Clients entgegennehmen. Die Anfragen leiten sie an die erforderlichen (internen, ggf. auch externen) Services weiter, führen die Ergebnisse zusammen und geben das Resultat an das Frontend zurück. Die Motive für die Nutzung dieser Gateways sind der Schutz der einzelnen Mikroservices vor Überlastung und Missbrauch sowie eine stabilere API-Schnittstelle des Backends gegenüber dem Frontend/den Frontends, da etwaige notwendige Änderungen der Mikroservices durch das API-Gateway verborgen werden können.
Load-Balancer sind eine Sonderform von API-Gateways auf dem Backend, die mehrere gleichwertige Endpunkte (mehrere Instanzen des gleichen Mikroservices) zusammenfassen. In der Praxis können die Funktionen eines klassischen Reverse Proxys und eines Load-Balancers in einer Komponente zusammengefasst sein.
Frontend-Entwicklung
Frontends für moderne Webanwendungen sind in der Regel Single-Page-Webseiten. Wie alle dynamischen Webseiten, werden sie mit HTML5, CSS und JavaScript (ab 1996) resp. TypeScript (ab 2012) implementiert.
Für die Umsetzung werden JavaScript-UI-Frameworks eingebunden. Frameworks erhöhen die Effizienz in der Webentwicklung durch a) die Verfügbarkeit vorgefertigter technischer Lösungen und b) die implizite Vorgabe von gemeinsamen Umsetzungsrichtlinien im Entwicklungsteam. Beide Vorteile ermöglichen erst die notwendige Skalierbarkeit und Wartbarkeit der immer komplexer werdenden Systeme. Nachteile (komplexer) Frameworks sind der resultierende Einarbeitungsaufwand, die Gefahr eines unnötigen Overheads sowie die zusätzlichen Abhängigkeiten.
Die heute am häufigsten verwendeten JavaScript-UI-Frameworks implementieren direkt oder indirekt einen komponenten-basierten Ansatz:
- React/React DOM (ab 2013): Frontend-Bibliothek entwickelt von Facebook. Weit verbreitet.
- Angular (ab 2010, vollständige Neu-Implementierung 2016): komponenten-basiertes Framework von Google
- Vue.js (ab 2014): das jüngste der großen drei aktuellen komponenten-basierten Frameworks
- Svelte (ab 2016): Anders als die o.g. Frameworks fungiert Svelte als Compiler, der Quellcode in imperativen JavaScript Code umwandelt. Svelte verzichtet auf das Konzept des Virtual DOM und weist eine hohe Effizienz zur Laufzeit auf.
- Ionic (ab 2013): Framework zur Entwicklung plattformübergreifender Apps in Angular, React oder Vue (sowie für native iOS- und Android-Apps)
Für Bestandsprojekte wichtige Frameworks sind:
- Angular JS (ab 2010): Bezeichnung der früheren Versionen vom heutigen Angular, Angular ist nicht rückwärtskompatible zu Angular JS, Long Term Support für Angular JS bis 12/2021 begrenzt
- Ember (ab 2011): eines der früheren, zeitweilig sehr bedeutsamen JavaScript-UI-Frameworks. Für neue Projekte von geringer Bedeutung.
- jQuery: Lange Jahre eine weit verbreitete und wichtige JavaScript-Bibliothek für die DOM-Manipulation von Webseiten und für deren einheitliche Darstellung auf unterschiedlichen Browsern – durch die zwischenzeitlich erfolgten Browserentwicklungen/Vereinheitlichungen (DOM, Renderengine Webkit) hat die Bibliothek allerdings ihre ursprüngliche Bedeutung verloren.
Zukünftig möglicherweise relevante Frameworks sind:
- Qwik: Sehr junge Bibliothek mit dem Fokus auf schnelles Laden von Webseiten. Beim initialen Aufruf der Webseite werden (fast) nur HTML-Anteile übertragen, die JavaScript-Anwendung wird nach Bedarf schrittweise nachgeladen. Die Interaktivität der Seite ist trotz des Nachladens der Anwendung von Anfang an gegeben.
Anstelle von originären CSS-Skripten werden u.U. CSS-Präprozessoren verwendet, wie SASS (ab 2007), Less oder Stylus, oder (ab 2017) das PostCSS Framework, mit dem vorhandene CSS-Skripte mit Hilfe von wählbaren Plugins transformiert werden können.
Ein Build-Prozess ist für Webseiten an sich nicht zwingend erforderlich, da ein „Kompilieren“ von Quellcode im herkömmlichen Sinne nicht notwendig ist und alle Bestandteile – HMTL, JS und CSS – prinzipiell unabhängig voneinander bereitgestellt und vom Browser geladen werden können.
Trotzdem wird bei der Erstellung komplexer Webanwendungen ein separater Build-Schritt eingefügt. Dieser deckt neben dem bereits erwähnten CSS-Präprozessing auch eine etwaige (derzeit noch) notwendige Umwandlung von ES6-JavaScript-Syntax (ECMAScript 2015+) mit Babel (seit 2014) in ES5-kompatiblen Code sowie eine etwaige notwendige Umwandlung von TypeScript in nativen JavaScript-Code ab, damit die Anwendung in allen aktuellen Browsern ausführbar ist.
Insbesondere beinhaltet der Build-Schritt aber auch die Zusammenführung (Bündelung) von mehreren (JavaScript-) Dateien zu einer (oder mehreren) komprimierten Datei(en) mit dem Ziel, die Netzwerkanforderungen im produktiven Betrieb beim Laden einer Anwendung zu reduzieren. Hierbei kommt traditionell webpack (ab 2012) oder das leichtgewichtigere, aber weniger aufwendig zu konfigurierende Parcel (ab 2017) oder das schelle esbuild (Version 1.0 2021/22) zum Einsatz.
Die Bündelung und Auslieferung einer einzigen großen, vollständig optimierten Source-Datei an den Browser ist unter Entwicklern nicht unumstritten, weil es in Folge bei komplexeren Projekten zu signifikanten Einbußen bei der Entwicklungsgeschwindigkeit kommen kann. So gehen neuere Build-Tools wie Snowpack (ab 2019), Vite (ab 2020) und wmr (ab 2020) einen differenzierteren Weg: Während für den produktiven Betrieb Bundles bereitgestellt werden, liefert der zugehörige Entwicklungsserver ungebündelte Dateien aus. Transformationen auf abhängige Module werden hier erst durchgeführt, wenn diese vom Browser explizit angefragt werden. Dieses Vorgehen beschleunigt die Entwicklungsarbeit erheblich.
Daten-Schnittstelle
Im Allgemeinen erfolgt die Kommunikation zwischen Webseiten und Webservern über das HTTP-Protokoll, welches im Internet unverschlüsselt im Klartext übertragen wird. Bei modernen Webanwendungen kommt jedoch fast nur noch die verschlüsselte HTTPS-Variante (Transportverschlüsselung mit SSL-Zertifikaten) zum Einsatz. Die Notwendigkeit der Verschlüsselung ergibt sich jedenfalls dann, wenn sensible, personenbezogene Daten wie z.B. Usernamen, Passwörter, Kontodaten usw. übertragen werden.
Wurden bei herkömmlichen Webanwendungen vom Backend „fertige“ HTML-Webseiten (statische Webseiten oder server-seitig gerenderte Templates) an das Frontend übertragen, bei denen jedenfalls etwaige Daten immer bereits in der HTML-Struktur integriert waren, werden bei modernen Webanwendungen Webseitenstruktur und anzuzeigenden Daten getrennt voneinander übermittelt.
Die Daten werden dabei durch der Ablaufsteuerung der Webseite explizit mit Hilfe eines AJAX-Requests (XMLHttpRequest) beim Backend abgefragt. Die Abfrage erfolgt typischerweise über zustandslose RESTful– oder GraphQL-Schnittstellen (Facebook, seit 2012/2015), die seitens des Backends bereitgestellt werden müssen. Die zur Übertragung der Daten verwendeten Datenformate sind JSON und (seltener) XML.
Um Daten auch ereignisgesteuert vom Backend an die Frontend-Clients übertagen zu können, wird (zusätzlich) eine WebSocket-Verbindung aufgebaut, die für die gesamte Dauer der Nutzung der Anwendung aufrecht bleibt. Die Implementierung der Web-Socketverbindung erfolgt z.B. über das Socket.IO-Framework.
Die etwaige Kommunikation eines Frontend mit mehreren Backends wird entweder vom Frontend direkt aus angestoßen oder indirekt wieder über ein zentrales API-Gateway vermittelt.
- Bei Vermittlung über eine zentrales API-Gateway auf dem Backend verteilt dieses die Anfragen nicht mehr (nur) an interne Mikroservices, sondern auch an externe Dienste innerhalb oder außerhalb der eigenen Firma.
- Ein direkter Aufruf von Funktionen auf dritten Backends (ohne API-Gateway) setzt Kenntnisse über diese Backends beim Frontend voraus. Er ist zudem immer mit einer faktischen Überschreitung der Same-Origin-Policy verbunden.
Ein Beispiel für einen direkten Aufruf eines weiteren Backends vom Frontend aus ist die Integration von Google Analytics Tracking Code im Quellcode der Webseite. Die genannte Same-Origin-Policy wird hier über ein single-pixel image request umgangen, bei der die gesammelten Daten als Aufruf-Parameter übergeben werden.
siehe auch: