# Funktionsweise von SSR:

## Teil 1: Apache-Konfigurationsdokumentation

## Allgemeine Informationen

Diese Konfigurationsdatei ist für einen Apache Webserver bestimmt und beinhaltet spezielle Regeln für das Umleiten von Anfragen und die Verarbeitung von Single Page Applications (SPAs).

## htaccess Konfigurationsdetails

-   MIME-Type Definition für .mjs Dateien
    -   AddType application/javascript .mjs
    -   Diese Anweisung sorgt dafür, dass Dateien mit der Endung .mjs als JavaScript-Dateien (application/javascript) behandelt werden.
-   Default Directory Index
    -   DirectoryIndex noindex
    -   Legt noindex als Standard-Indexdatei fest, wenn ein Verzeichnis aufgerufen wird. Dies verhindert, dass Apache automatisch eine Datei wie index.html oder spa.html lädt, wenn keine spezifische Datei in der URL angegeben ist. -> Emöglicht SSR
-   mod_rewrite Konfiguration
    -   IfModule mod_rewrite.c
        -   Diese Sektion ist nur aktiv, wenn das mod_rewrite-Modul verfügbar ist. mod_rewrite ermöglicht die Umleitung und Umformung von URLs.
    -   RewriteEngine On
        -   Aktiviert die Umleitungsfunktionen von mod_rewrite.
    -   RewriteBase /
        -   Setzt den Basispfad für Rewrite-Regeln auf das Wurzelverzeichnis.
    -   API-Umleitung
        -   RewriteRule ^/?api/(.*)$ http://tibi-server:8080/api/v1/_/vde8_tibi_2023/$1 [P,QSA,L]
            -   Leitet Anfragen, die mit /api/ beginnen, an einen anderen Server (tibi-server) um. Behält den Rest des Pfades bei und fügt ihn an den Ziel-URL an. Die Flags bedeuten:
            -   [P] Proxy: Die Anfrage wird intern an den angegebenen Server weitergeleitet.
            -   [QSA] Query String Append: Erhält bestehende Query-Parameter.
            -   [L] Last: Keine weiteren Regeln werden verarbeitet, wenn diese Regel greift.
    -   Fallback für Nichtexistierende Dateien/Verzeichnisse
        -   RewriteCond %{REQUEST_FILENAME} !-f und RewriteCond %{REQUEST_FILENAME} !-d
            -   Prüft, ob der angeforderte Pfad weder einer existierenden Datei noch einem Verzeichnis entspricht.
        -   RewriteRule ^/?(.*)$ http://tibi-server:8080/api/v1/_/vde8_tibi_2023/ssr?token=XYZ&url=/$1 [P,QSA,L]
            -   Leitet Anfragen, die nicht existierenden Dateien/Verzeichnissen entsprechen, an einen Server-seitigen Rendering-Prozess weiter.
            -   token=XYZ muss an den SSR_TOKEN angepasst werden (welcher auch in der server seinigen env steht.)
-   Kommentierte Regel
    -   #RewriteRule (.*) /spa.html [QSA,L]
    -   Eine auskommentierte Regel, die alle Anfragen zu spa.html umleiten würde. Da sie auskommentiert ist, hat sie keinen Effekt.

### Zusätzliche Hinweise

-   Die Konfiguration ist speziell für die Handhabung von Single Page Applications und API-Anfragen zugeschnitten.
-   Es ist wichtig, dass das mod_rewrite-Modul aktiviert ist, damit diese Regeln funktionieren.
-   Die Reihenfolge der Regeln ist entscheidend für die korrekte Funktionsweise.

## Teil 2: Grundlegender SSR-Prozess

-   Initiale Anfrage und Umleitung
    -   Anfragen für spa.html werden durch die .htaccess-Datei umgeleitet zur SSR-Collection.
    -   Der originale Pfad wird als URL-Query-Parameter an die neue URL angehängt.
    -   Beispiel: Eine Anfrage an /dimitrisBuecher/veraltet wird umgeleitet, da die /api/ Rewrite-Regel nicht greift.
-   Verarbeitung im Tibi-Server
    -   Gibt die Angefrage Seite zurück.

## Teil 3: Detaillierte Erklärung des Caching und Rendering-Prozesses im SSR-Kontext

-   URL-Extraktion im SSR-Hook
    -   Der Prozess beginnt mit der Extraktion der URL im SSR-Hook.
    -   Diese Extraktion dient als Grundlage für die nachfolgenden Schritte des Rendering-Prozesses.
-   Optionale Unterbindung von Caching
    -   Ein Boolean-Feld namens „Caching“ kann in der Content-Collection implementiert werden, um Caching selektiv zu steuern oder zu unterbinden.
    -   URL-Normalisierung und Existenzprüfung
    -   Die URL wird normalisiert, um Konsistenz zu gewährleisten.
    -   Anschließend wird überprüft, ob die normalisierte URL bereits in der SSR-Collection vorhanden ist.
    -   Für zeitlich begrenzte Sichtbarkeit von Seiten wird ein validUntil-Feld im Cache eingeführt und überprüft.(Nur wenn es für die Seite notwendig ist implementieren - aktuell in vde8 mit drin)
-   Validierung des Pfades
    -   Der Pfad wird validiert, indem geprüft wird, ob die URL als Pfad in der Content-Collection existiert.
        -   Rückgabewerte bei der Validierung:
            -   -1, wenn der Pfad nicht gefunden wird (not found).
            -   0, wenn der Pfad existiert, aber nicht gecacht werden darf.
            -   1, wenn der Pfad existiert und gecacht werden darf.
-   Cache-Vorbereitung bei Erlaubnis
    -   Bei Erlaubnis zum Cachen wird im Kontext-Objekt das ssrCache-Objekt sowie die ssrRequest-Funktion initialisiert.
    -   Diese Initialisierung ist entscheidend für das serverseitige App-Rendering.
-   Serverseitiges App-Rendering
    -   In Server-Umgebungen (überprüft durch typeof window == "undefined") werden keine normalen Fetch-Requests ausgeführt, sondern stattdessen die ssrRequest-Funktion verwendet.
    -   Zugriff auf das Kontext-Objekt ist auch im serverseitigen App-Reader möglich, was die Nutzung der ssrRequest-Funktion ermöglicht.
-   Setzen von ValidUntil und Durchführung der SSR-Request
    -   ValidUntil wird gesetzt, indem relevante Datensätze über context.db.find abgerufen werden.
    -   Überprüfung, ob Datensätze ein publishDate-Feld haben und ob dieses Datum relevant für das validUntil-Datum ist.
    -   Eine Request wird an die URL gesendet, das Ergebnis wird dann im ssrCache gespeichert.
-   Cache-Key Generierung
    -   Der Cache-Key wird generiert, indem ein Objekt, das aus dem Endpoint und relevanten Parametern besteht, in einen String konvertiert wird.
    -   Als Wert wird die standardmäßige Response aus dem Frontend verwendet.
-   Speicherung von Header und Body des Renderings
    -   Nach dem App-Rendering werden Header und Body in Variablen head und html gespeichert.
    -   Ein script-Tag, das window.**SSR_CACHE** auf context.ssrCache setzt, wird zum Header hinzugefügt.
-   Clientseitige Fetch-Request-Optimierung
    -   Überprüfung, ob die aktuelle Anfrage bereits im window.**SSR_CACHE** vorhanden ist.
    -   Bei vorhandenen Anfragen wird der gespeicherte Wert über Promise.resolve() zurückgegeben, um redundante Anfragen zu vermeiden.
-   Deaktivierung von SSR-Caching für spezielle Seiten
    -   Für Seiten wie Produktseiten wird empfohlen, das SSR-Caching über den Boolean zu deaktivieren, um zu verhindern, dass solche Anfragen in den Cache gelangen.
-   Finalisierung des HTML-Dokuments
    -   Das Standard-spa.html-Dokument wird verwendet und mit den ermittelten Werten für Head, Body, Fehlermeldungen und Kommentaren ergänzt.
    -   Das resultierende HTML-Dokument wird in der SSR-Collection gespeichert und als Response an den Client gesendet.
-   Ergebnis
    -   Der Client erhält eine vollständig gerenderte HTML-Seite, die serverseitig verarbeitet wurde, was die Effizienz erhöht und die Notwendigkeit zahlreicher Requests reduziert.

## Teil 3: SSR-Cache-Management

-   Cache-Management in der Content-Collection
    -   Löschung der SSR-Collection bei jedem POST und PUT-Request.
-   Workflow-Integration
    -   Als Teil des Workflows wird der SSR-Cache gelöscht, um die Auslieferung veralteter Seiten zu verhindern.

### Dokumentation: SSR in der Entwicklungsumgebung

#### Überblick

In der Entwicklungsumgebung unterscheidet sich der Umgang mit Server-Side Rendering (SSR) von der Produktion, da hier die .htaccess keine Rolle spielt. Es sind spezielle Maßnahmen bei der Konfiguration von esbuild erforderlich.

#### Schritte für die SSR-Konfiguration in der Entwicklungsumgebung

-   Anpassung der .env-Datei
    -   Setzen von START_SCRIPT=:ssr in der .env-Datei.
    -   Diese Einstellung wird in der Docker-compose-Datei verwendet, um zu bestimmen, welches Startskript für das Frontend verwendet werden soll.
    -   Auch auf dem Server muss logischerweise der SSR_TOKEN in der env gesetzt sein, damit einerseits die yml config Datei darauf zugreifen kann, aber esbuild auch darauf zugreifen kann (in der htaccess wird er statisch geschrieben)
-   Verwendung von start:ssr
    -   Bei Verwendung von start:ssr wird die SSR-Variable gesetzt.
    -   Diese Variable ist notwendig für esbuild, um zu entscheiden, ob ein Proxy aktiviert werden soll.
    -   Proxy-Funktionalität in esbuild
    -   Der Proxy in esbuild übernimmt die Rolle der .htaccess.
    -   Er leitet Anfragen, die normalerweise an spa.html gehen würden, an die SSR-Collection weiter.
-   Handhabung von Frontend-Änderungen
    -   Änderungen am Frontend werden nicht automatisch in SSR übernommen.
    -   Um die serverseitig vorliegende Version der App zu aktualisieren, muss yarn Build:server ausgeführt werden.
-   Bewusster manueller Prozess
    -   Eine automatische Übernahme von Änderungen könnte die Ladezeiten nach einem Reload erheblich erhöhen.
    -   Um die Effizienz der Entwicklungsumgebung zu erhalten, wird der manuelle Prozess bevorzugt.
-   Notwendige Nachbearbeitung nach Updates
    -   Nach dem Neubau der serverseitigen App-Version müssen aktuelle SSR-Einträge gelöscht werden.
    -   Ein Reboot des Tibi-Servers (durch Speichern in den Einstellungen) ist erforderlich, damit dieser die neue App-Version in den Cache aufnimmt.
-   Integration von SSR im Entwicklungsprozess
    -   Aufgrund des aufwendigeren Prozesses wird empfohlen, SSR erst in einem späteren Stadium der Entwicklung zu integrieren.
    -   Dies ermöglicht eine effizientere Entwicklung ohne SSR, bevor dieses für die finale Version implementiert wird.

### Anmerkungen:

Anzumerken ist, dass alle zugriffe auf window, document, oder Funktionen wie setTimeout in der frontend app beim SSR Fehler werfen werden, daher muss immer eine Prüfung sicherstellen, das window nicht undefined ist.

In der notFound komponente sollte man idealerweise context.is404 auf true setzen, damit sichergestellt wird, das die Seite unter keinen umständen gecached wird (backup zur vorherigen Prüfung in isValidPath Funktion…)

Natürlich muss in der Serverseitigen env der entsprechende key für SSR access gesetzt werden. Dieser wird in esbuild gelesen und ist damit notwendig
