Render Caching für React

Avatar of Atishay Jain
Atishay Jain am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Server Side Rendering (SSR) ist eine sehr nützliche Technik, die Web-Apps schneller erscheinen lässt. Die anfängliche HTML wird angezeigt, bevor das JavaScript geparst wird, und während der Benutzer entscheidet, worauf er tippen soll, sind unsere Handler bereit.

Server-Side-Rendering in React erfordert zusätzliche Arbeit bei der Einrichtung und verursacht Serverkosten. Darüber hinaus, wenn Ihr Serverteam keine JavaScript-Ausführung auf Ihren Servern durchführen kann, sind Sie gefangen. Es kompliziert die Einrichtung des CDN erheblich, insbesondere wenn Sie Seiten haben, die ein Login erfordern und bei denen die Benutzerinformationen verwaltet werden.

Ich möchte ein neues Konzept namens Render Caching vorstellen. Dies ist ein cooler Trick, der Benutzern eine sofortige Leistungssteigerung wie bei SSR bieten kann, ohne dass Code auf dem Server geschrieben werden muss.

Was ist Render Caching?

Die Migration von statischen HTML-Seiten zu Single Page Apps (SPAs) hat eine klaffende Lücke im gesamten Konzept des Cachings hinterlassen, auf das sich das Web traditionell verlassen hat. Während Browser die Auslieferung und das Rendern des anfänglichen HTML optimieren, lässt eine SPA diese leer, um später gefüllt zu werden.

Render Caching optimiert das SPA-Rendering und kann die wahrgenommene Ladezeit von Webseiten erheblich verbessern. Dies geschieht durch das Caching des gerenderten HTML im Browser für den nächsten Ladevorgang und kann diese Anzeige ohne das Parsen von JavaScript bereitstellen, das unsere Anzeigezeit beansprucht.

Render Caching aktivieren

Wir haben bereits erwähnt, dass die Einrichtung von SSR für React zusätzlichen Aufwand und Serverkosten verursacht. Render Caching vermeidet diese Belastungen.

Die Einrichtung erfordert ein paar Schritte. Lassen Sie uns das in verdauliche Stücke aufteilen.

Schritt 1: Ermitteln des korrekten Caching-Zustands

Finden Sie die Bedingungen für die aktuelle Seite heraus, bei denen sie bei einem erneuten Besuch des Benutzers gleich gerendert wird.

Sie könnten zum Beispiel ein JSON-Objekt mit der aktuellen Build-Nummer oder einer Benutzer-ID erstellen. Entscheidend ist, dass der Zustand in der URL, im lokalen Speicher oder in Cookies gekapselt ist und kein Serveraufruf dafür benötigt wird.

Schritt 2: API-Aufrufe einrichten

Stellen Sie sicher, dass alle API-Aufrufe vor dem Renderaufruf an React erfolgen. Das ist auch in regulären Anwendungsfällen sinnvoll, wo wir verhindern wollen, dass sich die Seite unter dem Benutzer ändert, was zu Flackern führt.

Schritt 3: Lokal im Unload-Handler cachen

Fügen Sie nun einen Unload-Event-Handler zum Dokument hinzu. Speichern Sie das aktuelle DOM in localStorage/indexDB.

Das sieht dann etwa so aus, wobei eine Build-Nummer und eine Benutzer-ID verwendet werden, um den in Schritt 1 behandelten Caching-Zustand zu bestimmen.

window.addEventListener("beforeunload", () => {
  // Production code would also be considerate of localStorage size limitations
  // and would do a LRU cache eviction to maintain sanity on storage.
  // There should also be a way to clear this data when the user signs out
  window.localStorage.setItem(
    `lastKnown_${window.location.href}`,
    JSON.stringify({
      conditions: {
        userId: "<User ID>",
        buildNo: "<Build No.>"
      },
      data: document.getElementById("content").innerHTML
    })
  );
});

// If you want to store data per user, you can add user ID to the key instead of the condition.

Schritt 4: Den letzten bekannten Zustand beim Laden wiederherstellen

Als Nächstes wollen wir den letzten bekannten Zustand aus dem lokalen Speicher des Browsers abrufen, um ihn bei zukünftigen Besuchen verwenden zu können. Dies tun wir, indem wir Folgendes zur HTML-Datei hinzufügen (z. B. `index.html` unter dem `body`-Tag des Dokuments).

<!-- ... -->
</body>

<script>
  let lastKnownState = window.localStorage.getItem(`lastKnown_${window.location.href}`);
  
  lastKnownState = lastKnownState && JSON.parse(lastKnownState);
  
  if (lastKnownState &&
    lastKnownState.conditions.userId === "<User ID>" &&
    lastKnownState.conditions.buildNo === "<Build No.>") {
    document.getElementById('content').innerHTML = lastKnownState.data;
    window.hasRestoredState = true;
  }
</script>

Schritt 5: Den letzten bekannten Zustand in React rendern

Hier wird es ernst. Nachdem wir nun den letzten bekannten Zustand des Benutzers im DOM sichtbar gemacht haben, können wir den vollständigen Inhalt abrufen und unsere App in diesem Zustand rendern, indem wir die oberste Ebene von Reacts Rendering mit hydrate bedingt aktualisieren. Event-Handler werden funktionsfähig, sobald dieser Code ausgeführt wird, aber das DOM sollte sich nicht ändern.

import {render, hydrate} from "react-dom"

if (window.hasRestoredState) {
  hydrate(<MyPage />, document.getElementById('content'));
} else {
  render(<MyPage />, document.getElementById('content'));
}

Schritt 6: Vollständig asynchron machen

Ändern Sie Ihre Skript-Tags von sync auf async/defer, um die JavaScript-Dateien zu laden. Dies ist ein weiterer wichtiger Schritt, um ein reibungsloses Lade- und Rendering-Erlebnis auf der Benutzeroberfläche zu gewährleisten.

Das ist alles! Laden Sie die Seite neu, um den Leistungsschub zu sehen.

Leistungsverbesserung messen

Okay, Sie haben all diese Arbeit geleistet und möchten nun wissen, wie performant Ihre Website ist. Sie werden die Verbesserungen benchmarken wollen.

Render Caching glänzt in Situationen, in denen Sie mehrere Serveraufrufe haben, bevor Sie wissen, was gerendert werden soll. Auf Skript-lastigen Seiten kann JavaScript tatsächlich viel Zeit zum Parsen beanspruchen.

Sie können die Ladeleistung im Tab "Performance" in den Chrome DevTools messen.

Messung des Renderns im Performance-Tab der Chrome DevTools

Idealerweise würden Sie ein Gastprofil verwenden, damit Ihre Browser-Erweiterungen die Messungen nicht stören. Sie sollten beim Neuladen eine deutliche Verbesserung feststellen. Im obigen Screenshot sehen wir eine Beispiel-App mit einem asynchronen `data.json`-Fetch-Aufruf, der vor dem Aufruf von `ReactDOM.hydrate` ausgeführt wird. Mit Render Caching ist das Rendering abgeschlossen, noch bevor die Daten geladen sind!

Zusammenfassung

Render Caching ist eine clevere Technik, um sicherzustellen, dass die wahrgenommene Geschwindigkeit von erneuten Abrufen derselben Webseite schneller ist, indem eine Caching-Schicht für das finale HTML hinzugefügt und diese dem Benutzer angezeigt wird. Benutzer, die Ihre Website häufig besuchen, profitieren am meisten.

Wie Sie sehen können, haben wir dies mit sehr wenig Code erreicht und die daraus resultierenden Leistungssteigerungen sind enorm. Probieren Sie es auf Ihrer Website aus und hinterlassen Sie Ihre Kommentare. Ich würde gerne erfahren, ob Ihre Website-Leistung die gleichen deutlichen Verbesserungen erzielt, die ich erfahren habe.