Routen vorab rendern – mit Reaktions-Snap

Sie verwenden kein serverseitiges Rendering, möchten aber die Leistung Ihrer React-Website verbessern? Probiere das Pre-Rendering aus.

react-snap ist eine Drittanbieterbibliothek, die Seiten auf Ihrer Website vorab in statische HTML-Dateien rendert. Dadurch kann die First Paint-Zeit in Ihrer Anwendung verbessert werden.

Hier ist ein Vergleich derselben Anwendung mit und ohne Pre-Rendering, die über eine simulierte 3G-Verbindung und ein Mobilgerät geladen wird:

Direkter Vergleich des Ladevorgangs Die Version mit Pre-Rendering wird 4,2 Sekunden schneller geladen.

Welchen Nutzen bieten sie?

Das Hauptproblem bei großen Single-Page-Anwendungen besteht darin, dass Nutzer warten müssen, bis das Herunterladen der JavaScript-Bundles, aus denen die Website besteht, abgeschlossen ist, bevor sie echte Inhalte sehen können. Je größer die Pakete sind, desto länger müssen die Nutzer warten.

Viele Entwickler rendern die Anwendung daher auf dem Server, anstatt sie nur im Browser zu starten. Bei jeder Seiten-/Wegüberleitung wird die gesamte HTML-Seite auf dem Server generiert und an den Browser gesendet. Dadurch wird die First Paint-Zeit verkürzt, aber die Time to First Byte wird verlängert.

Das Vorab-Rendering ist eine separate Methode, die weniger komplex als das Server-Rendering ist, aber auch eine Möglichkeit bietet, die Zeit bis zur ersten Darstellung in Ihrer Anwendung zu verbessern. Mit einem Headless-Browser (d. h. einem Browser ohne Benutzeroberfläche) werden während der Buildzeit statische HTML-Dateien für jede Route generiert. Diese Dateien können dann zusammen mit den für die Anwendung erforderlichen JavaScript-Bundles bereitgestellt werden.

react-snap

react-snap verwendet Puppeteer, um vorab gerenderte HTML-Dateien verschiedener Routen in Ihrer Anwendung zu erstellen. Installieren Sie es zuerst als Entwicklungsabhängigkeit:

npm install --save-dev react-snap

Fügen Sie dann ein postbuild-Script in package.json ein:

"scripts": {
  //...
  "postbuild": "react-snap"
}

Dadurch wird der Befehl react-snap jedes Mal automatisch ausgeführt, wenn ein neuer Build der Anwendungen erstellt wird (npm build).

Als Letztes müssen Sie die Bootmethode der Anwendung ändern. Ändern Sie die Datei src/index.js so:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));
const rootElement = document.getElementById("root");

if (rootElement.hasChildNodes()) {
  ReactDOM.hydrate(<App />, rootElement);
} else {
  ReactDOM.render(<App />, rootElement);
}

Anstatt nur ReactDOM.render zu verwenden, um das Stamm-React-Element direkt in das DOM zu rendern, wird geprüft, ob bereits untergeordnete Knoten vorhanden sind, um zu bestimmen, ob HTML-Inhalte vorab gerendert (oder auf dem Server gerendert) wurden. In diesem Fall wird stattdessen ReactDOM.hydrate verwendet, um Ereignis-Listener an die bereits erstellte HTML-Datei anzuhängen, anstatt sie neu zu erstellen.

Beim Erstellen der Anwendung werden jetzt statische HTML-Dateien als Nutzlast für jede gecrawlte Route generiert. Sie können sich die HTML-Nutzlast ansehen, indem Sie auf die URL der HTML-Anfrage und dann in den Chrome DevTools auf den Tab Vorschauen klicken.

Ein Vorher-Nachher-Vergleich. In der Nachbearbeitung ist zu sehen, dass der Inhalt gerendert wurde.

Blitzen von nicht formatierten Inhalten

Obwohl statische HTML-Inhalte jetzt fast sofort gerendert werden, bleiben sie standardmäßig ohne Stil. Dies kann zu einem „Flash of unstyled content“ (FOUC) führen. Das kann besonders auffallen, wenn Sie eine CSS-in-JS-Bibliothek zum Generieren von Selektoren verwenden, da die Ausführung des JavaScript-Bundles abgeschlossen sein muss, bevor Stile angewendet werden können.

Um dies zu verhindern, kann das kritische CSS oder die Mindestmenge an CSS, die zum Rendern der Startseite erforderlich ist, direkt in die <head> des HTML-Dokuments eingefügt werden. react-snap verwendet eine weitere Drittanbieterbibliothek namens minimalcss, um alle wichtigen CSS-Dateien für verschiedene Routen zu extrahieren. Sie können dies aktivieren, indem Sie Folgendes in Ihrer package.json-Datei angeben:

"reactSnap": {
  "inlineCss": true
}

In der Antwortvorschau in den Chrome-Entwicklertools wird jetzt die Seite mit Stil und Inline-CSS angezeigt.

Ein Vorher-Nachher-Vergleich. In der Nachher-Aufnahme ist zu sehen, dass der Inhalt gerendert wurde und aufgrund von Inline-kritischen CSS-Stilen gestaltet wurde.

Fazit

Wenn Sie Routen in Ihrer Anwendung nicht serverseitig rendern, verwenden Sie react-snap, um statischen HTML-Code für Ihre Nutzer vorab zu rendern.

  1. Installieren Sie es als Entwicklungsabhängigkeit und beginnen Sie nur mit den Standardeinstellungen.
  2. Verwenden Sie die experimentelle Option inlineCss, um kritisches CSS inline einzubetten, wenn dies für Ihre Website funktioniert.
  3. Wenn Sie die Codeaufteilung auf Komponentenebene innerhalb von Routen verwenden, darf im Voraus kein Ladestatus für Ihre Nutzer gerendert werden. Weitere Informationen dazu finden Sie in der README-Datei zu react-snap.