Architektur

Wenn Sie Ihre Anwendung so entwerfen möchten, dass Sie die Technologie optimal nutzen können, die PWAs zuverlässig, installierbar und leistungsfähig macht, müssen Sie Ihre Anwendung und ihre Einschränkungen verstehen und eine geeignete Architektur für beides auswählen.

SPA im Vergleich zu MPA

Heutzutage gibt es zwei grundlegende Architekturmuster in der Webentwicklung: Single-Page-Apps (SPAs) und mehrseitige Apps (MPAs).

Bei Apps mit nur einer Seite wird mit clientseitigem JavaScript der Großteil oder das gesamte HTML-Rendering einer Seite gesteuert, je nachdem, welche Daten von der App abgerufen oder an sie gesendet werden. Die App überschreibt die integrierte Navigation des Browsers und ersetzt sie durch die Routing- und Ansichtsverwaltungsfunktionen.

Bei mehrseitigen Apps wird in der Regel vorab gerenderter HTML-Code direkt an den Browser gesendet. Dieser wird häufig mit clientseitigem JavaScript optimiert, nachdem der Browser den HTML-Code geladen hat, und greifen bei der Anzeige nachfolgender Ansichten auf die integrierten Navigationsmechanismen des Browsers.

Beide Architekturen können zum Erstellen von PWAs verwendet werden.

Jede dieser Optionen hat Vor- und Nachteile. Die richtige Auswahl für Ihren Anwendungsfall und Ihren Kontext ist entscheidend, um Ihren Nutzern eine schnelle und zuverlässige Erfahrung zu bieten.

Einseitige Apps

Vorteile
  • Überwiegend atomare In-Page-Updates.
  • Clientseitige Abhängigkeiten, die beim Start geladen werden.
  • Nachfolgende Ladevorgänge sind aufgrund der Cache-Nutzung schnell.
Nachteile
  • Hohe Kosten für das anfängliche Laden.
  • Die Leistung hängt von der Gerätehardware und der Netzwerkverbindung ab.
  • Zusätzliche App-Komplexität ist erforderlich.

Einseitige Apps sind in folgenden Fällen eine gute Architektur:

  • Die Nutzerinteraktion konzentriert sich hauptsächlich auf atomare Updates von miteinander verbundenen Daten, die auf derselben Seite angezeigt werden, z. B. ein Echtzeit-Daten-Dashboard oder eine Videobearbeitungs-App.
  • Ihre Anwendung hat nur clientseitige Initialisierungsabhängigkeiten, z. B. ein externer Authentifizierungsanbieter mit extrem hohen Startkosten.
  • Die zum Laden einer Ansicht erforderlichen Daten basieren auf einem bestimmten, nur clientseitigen Kontext, beispielsweise, in dem Steuerelemente für eine verbundene Hardware angezeigt werden.
  • Die App ist so klein und einfach, dass sich ihre Größe und Komplexität nicht auf die oben genannten Nachteile auswirken.

SPAs sind in folgenden Fällen möglicherweise keine gute Architektur:

  • Die anfängliche Ladeleistung ist entscheidend. SPAs müssen normalerweise mehr JavaScript laden, um zu bestimmen, was geladen und wie es angezeigt werden soll. Die Analyse- und Ausführungszeit dieses JavaScripts sowie das Abrufen von Inhalten dauert länger als das Senden von gerendertem HTML-Code.
  • Ihre App läuft hauptsächlich auf Geräten mit geringer bis durchschnittlicher Leistung. Da SPAs zum Rendern auf JavaScript angewiesen sind, hängt die Nutzererfahrung wesentlich stärker von der Leistung des jeweiligen Geräts als bei einem MPA ab.

Da SPAs die integrierte Navigation des Browsers durch ihre Routenführung ersetzen müssen, erfordern SPAs ein minimales Maß an Komplexität in Bezug auf die effiziente Aktualisierung der aktuellen Ansicht, die Verwaltung von Navigationsänderungen und die Bereinigung früherer Ansichten, die sonst vom Browser verarbeitet werden würden. Dadurch wird die Wartung insgesamt schwieriger und das Gerät des Nutzers wird stärker beansprucht.

Mehrseitige Apps

Vorteile
  • Meistens ganzseitige Aktualisierungen.
  • Die anfängliche Renderinggeschwindigkeit ist entscheidend.
  • Clientseitiges Scripting kann eine Verbesserung sein.
Nachteile
  • Sekundäre Ansichten erfordern einen weiteren Serveraufruf.
  • Der Kontext wird nicht auf andere Aufrufe übertragen.
  • Erfordert einen Server oder Pre-Rendering.

Mehrseitige Apps sind in folgenden Fällen eine gute Architektur:

  • Die Nutzerinteraktion konzentriert sich hauptsächlich auf die Ansicht einzelner Daten mit optionalen kontextbasierten Daten, z. B. einer Nachrichten- oder E-Commerce-App.
  • Die anfängliche Rendering-Geschwindigkeit ist entscheidend, da das Senden von bereits gerendertem HTML-Code an den Browser schneller ist als das Zusammenstellen aus einer Datenanforderung nach dem Laden, Parsen und Ausführen einer JavaScript-basierten Alternative.
  • Clientseitige Interaktivität oder Kontext können nach dem anfänglichen Laden als Optimierung hinzugefügt werden. So kann beispielsweise ein Profil auf eine gerenderte Seite überlagert oder sekundäre clientseitige kontextabhängige Komponenten hinzugefügt werden.

MPAs sind in folgenden Fällen möglicherweise keine gute Architekturentscheidung:

  • Das erneute Herunterladen, erneute Analysieren und Ausführen von JavaScript oder CSS ist zu teuer. Dieser Nachteil wird bei PWAs mit Service Workern abgemildert.
  • Clientseitiger Kontext wie der Nutzerstandort wird nicht nahtlos zwischen Ansichten übertragen, und das erneute Abrufen dieses Kontexts kann teuer sein. Sie müssen entweder erfasst und abgerufen oder zwischen Ansichten noch einmal angefordert werden.

Weil einzelne Ansichten dynamisch von einem Server gerendert oder vorab gerendert werden müssen, bevor sie darauf zugreifen können. Dadurch kann das Hosting eingeschränkt oder die Datenkomplexität erhöht werden.

Für welche Option?

Trotz dieser Vor- und Nachteile sind beide Architekturen für die Erstellung Ihrer PWA geeignet. Sie können sie sogar für verschiedene Teile Ihrer App mischen, je nach deren Anforderungen. So können Sie beispielsweise festlegen, dass Store-Einträge einer MPA-Architektur folgen und der Bezahlvorgang einer SPA-Architektur folgt.

Unabhängig von ihrer Wahl besteht der nächste Schritt darin, zu verstehen, wie Service Worker am besten eingesetzt werden können, um die bestmögliche Erfahrung zu bieten.

Das Potenzial des Service Workers

Der Service Worker verfügt über viel Macht über das grundlegende Routing und die Übermittlung von zwischengespeicherten und Netzwerkantworten hinaus. Wir können komplexe Algorithmen erstellen, um die Nutzererfahrung und Leistung zu verbessern.

Service Worker-Includes (SWI)

Ein neues Muster für die Verwendung von Service Workern als integraler Bestandteil der Architektur eines Standorts ist Service Worker Includes (SWI). SWI teilt einzelne Assets, in der Regel eine HTML-Seite, entsprechend ihren Caching-Anforderungen in Teile auf und fügt sie dann im Service Worker wieder zusammen, um Konsistenz, Leistung und Zuverlässigkeit zu verbessern und gleichzeitig die Cache-Größe zu reduzieren. Eine Website mit einer globalen Kopfzeile, einem Inhaltsbereich, einer Seitenleiste und einer Fußzeile.

Dieses Bild ist eine Beispielwebseite. Sie besteht aus fünf verschiedenen Abschnitten, die die Seite in folgende Bereiche unterteilen:

  • Gesamtlayout
  • Globale Kopfzeile (dunkle Leiste oben)
  • Inhaltsbereich (mittlere linke Linien und Bild)
  • Seitenleiste (hohe mitteldunkle Leiste rechts in der Mitte).
  • Fußzeile (dunkle untere Leiste).

Gesamtlayout

Das Gesamtlayout ändert sich wahrscheinlich nicht oft und weist keine Abhängigkeiten auf. Es eignet sich gut für das Precaching.

Die globale Kopf- und Fußzeile enthalten Elemente wie das obere Menü und die Fußzeile der Website und stellen eine besondere Herausforderung dar: Wenn die Seite insgesamt im Cache gespeichert werden soll, können sich diese zwischen Seitenladevorgängen ändern, je nachdem, wann die jeweilige Seite im Cache gespeichert wurde.

Indem Sie sie voneinander trennen und unabhängig vom Inhalt im Cache speichern, können Sie sicherstellen, dass Nutzer immer die gleiche Version erhalten, unabhängig davon, wann sie im Cache gespeichert sind. Da sie nur selten aktualisiert werden, eignen sie sich auch gut für das Precaching. Sie sind jedoch abhängig vom CSS- und JavaScript-Code der Website.

CSS und JavaScript

Idealerweise sollten CSS- und JavaScript-Code der Website mit einer veralteten Strategie zur Neuvalidierung im Cache gespeichert werden, um inkrementelle Updates zu ermöglichen, ohne den Service Worker aktualisieren zu müssen, wie es bei vorab im Cache gespeicherten Assets der Fall ist. Dennoch müssen sie auch auf einer Mindestversion gehalten werden, wenn der Service Worker mit einer neuen globalen Kopf- oder Fußzeile aktualisiert. Aus diesem Grund sollte auch der Cache des Service Workers mit der neuesten Asset-Version aktualisiert werden.

Inhaltsbereich

Als Nächstes folgt der Inhaltsbereich. Je nach Häufigkeit der Updates ist hier entweder das Netzwerk zuerst oder veraltet während der erneuten Validierung eine gute Strategie. Bilder sollten mit einer Cache-First-Strategie zwischengespeichert werden, wie bereits bereits erwähnt.

Wenn der Inhalt der Seitenleiste sekundäre Inhalte wie Tags und verwandte Elemente enthält, ist ein Abruf aus dem Netzwerk nicht kritisch genug. Hier können Sie eine veraltete Strategie zur erneuten Validierung verwenden.

Nachdem Sie all dies durchgegangen sind, denken Sie vielleicht, dass diese Art von Caching pro Abschnitt nur für Apps mit nur einer Seite möglich ist. Durch die Übernahme von Mustern, die auf Edge-Side-Includes oder Server Side Includes basieren, mit einigen erweiterten Service Worker-Funktionen, können Sie dies jedoch für beide Architekturen tun.

Selbst ausprobieren

Sie können die im Service Worker enthaltenen Elemente im nächsten Codelab ausprobieren:

Streamingantworten

Die vorherige Seite könnte mit dem App-Shell-Modell in der SPA-Welt erstellt werden. Dabei wird die App-Shell im Cache gespeichert, dann bereitgestellt und die Inhalte werden clientseitig geladen. Mit der Einführung und der umfassenden Verfügbarkeit der Streams API können sowohl die Anwendungs-Shell als auch der Inhalt im Service Worker kombiniert und an den Browser gestreamt werden. So haben Sie die Flexibilität der Anwendungs-Shell im Cache mit der Geschwindigkeit von MPAs.

Dies geschieht aus folgenden Gründen:

  • Streams können asynchron erstellt werden, sodass verschiedene Teile eines Streams aus anderen Quellen stammen können.
  • Der Anforderer eines Streams kann mit der Bearbeitung der Antwort beginnen, sobald der erste Datenblock verfügbar ist. Er muss also nicht warten, bis das gesamte Element abgeschlossen ist.
  • Für Streaming optimierte Parser, einschließlich Browser, können den Inhalt des Streams schrittweise anzeigen, bevor dieser abgeschlossen ist. Dadurch wird die wahrgenommene Leistung der Antwort beschleunigt.

Dank dieser drei Eigenschaften von Streams wird die Leistung von Architekturen, die auf Streaming basieren, in der Regel schneller wahrgenommen als andere.

Die Arbeit mit der Streams API kann eine Herausforderung sein, da sie komplex und auf niedriger Ebene ist. Zum Glück gibt es ein Workbox-Modul, das Sie bei der Einrichtung von Streamingantworten für Ihre Service Worker unterstützen kann.

Domains, Ursprünge und PWA-Bereich

Web Worker, einschließlich Service Worker, Speicher und sogar das Fenster einer installierten PWA, unterliegen einem der wichtigsten Sicherheitsmechanismen im Web: der Same-Origin-Policy. Innerhalb desselben Ursprungs werden Berechtigungen gewährt, Daten können freigegeben werden und der Service Worker kann mit verschiedenen Clients kommunizieren. Außerhalb desselben Ursprungs werden Berechtigungen nicht automatisch gewährt und die Daten sind isoliert und nicht von verschiedenen Ursprüngen aus zugänglich.

Richtlinie für denselben Ursprung

Zwei URLs haben den genauen Ursprung, wenn Protokoll, Port und Host identisch sind.

Beispiel: https://squoosh.app und https://squoosh.app/v2 haben denselben Ursprung, aber http://squoosh.app, https://squoosh.com, https://app.squoosh.app und https://squoosh.app:8080 haben unterschiedliche Ursprünge. Weitere Informationen und Beispiele finden Sie in der MDN-Referenz für die Same-Origin-Richtlinie.

Das Ändern von Subdomains ist nicht die einzige Möglichkeit für Hosts. Jeder Host besteht aus einer Top-Level-Domain (TLD), einer Second-Level-Domain (SLD) und null oder mehr Labels (manchmal auch Subdomains genannt), die durch Punkte dazwischen getrennt sind und in einer URL von rechts nach links gelesen werden. Eine Änderung an einem der Elemente führt zu einem anderen Host.

Im Modul zur Fensterverwaltung haben wir bereits gesehen, wie der In-App-Browser aussieht, wenn ein Nutzer von einer installierten PWA zu einem anderen Ursprung navigiert.

Dieser In-App-Browser wird auch dann angezeigt, wenn die Websites dieselbe TLD und SLD haben, aber mit unterschiedlichen Labels, da sie dann als unterschiedlicher Ursprung betrachtet werden.

Einer der wichtigsten Aspekte eines Ursprungs im Web-Browser-Kontext ist die Funktionsweise des Speichers und der Berechtigungen. Ein Ursprung hat viele Funktionen für alle Inhalte und die darin enthaltenen PWAs, darunter:

  • Speicherkontingent und Daten (IndexedDB, Cookies, Webspeicher, Cache-Speicher)
  • Service Worker-Registrierungen.
  • Gewährte oder abgelehnte Berechtigungen (z. B. Web-Push, Standortbestimmung, Sensoren)
  • Web-Push-Registrierungen

Wenn Sie von einem Ursprung zu einem anderen wechseln, wird der gesamte bisherige Zugriff widerrufen. Daher müssen die Berechtigungen neu erteilt werden und Ihre PWA kann nicht auf alle im Speicher gespeicherten Daten zugreifen.

Ressourcen