Routen vorab rendern – mit Reaktions-Snap

Sie verwenden kein serverseitiges Rendering, möchten aber die Leistung Ihrer React-Website verbessern? Versuchen Sie es mit Pre-Rendering!

react-snap ist eine Bibliothek eines Drittanbieters, über die Seiten Ihrer Website vorab in statische HTML-Dateien gerendert werden. Dies kann die First Paint-Zeiten in Ihrer Anwendung verbessern.

Im Folgenden wird die gleiche Anwendung mit und ohne Pre-Rendering auf einer simulierten 3G-Verbindung und auf einem Mobilgerät verglichen:

Ein Vergleich im direkten Vergleich Die Version, für die Pre-Rendering verwendet wird, lädt 4,2 Sekunden schneller.

Welchen Nutzen bieten sie?

Das größte Leistungsproblem bei großen Single-Page-Anwendungen besteht darin, dass der Nutzer erst nach dem Download der JavaScript-Bundles für die Website warten muss, bevor er echte Inhalte sehen kann. Je größer die Bundles, desto länger muss der Nutzer warten.

Um dieses Problem zu lösen, rendern viele Entwickler die Anwendung auf dem Server, anstatt sie nur im Browser zu starten. Bei jedem Seiten-/Routenübergang wird der vollständige HTML-Code auf dem Server generiert und an den Browser gesendet, was die First Paint-Zeiten verkürzt, aber auf Kosten einer langsameren Time to First Byte-Zeit geht.

Das Pre-Rendering ist eine separate Technik, die weniger komplex als das Server-Rendering ist, aber auch eine Möglichkeit bietet, die First Paint-Zeiten in Ihrer Anwendung zu verkürzen. Ein monitorloser Browser bzw. ein Browser ohne Benutzeroberfläche wird verwendet, um während der Build-Zeit statische HTML-Dateien für jede Route zu generieren. Diese Dateien können dann zusammen mit den JavaScript-Bundles ausgeliefert werden, die für die Anwendung benötigt werden.

Reaktion/Snap

react-snap verwendet Puppeteer, um vorgerenderte 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-Skript 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 ändern, wie die Anwendung gestartet wird. Ä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 React-Stammelement direkt im DOM zu rendern, wird geprüft, ob untergeordnete Knoten bereits vorhanden sind, um festzustellen, ob HTML-Inhalte vorab gerendert oder auf dem Server gerendert wurden. In diesem Fall wird stattdessen ReactDOM.hydrate verwendet, um Ereignis-Listener an den bereits erstellten HTML-Code anzuhängen, anstatt ihn neu zu erstellen.

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

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

Blitz mit Inhalten ohne Design

Obwohl statischer HTML-Code jetzt fast sofort gerendert wird, bleibt er standardmäßig immer noch unbeschriftet, was dazu führen kann, dass ein „Flash of Unstyled Content“ (FOUC) angezeigt wird. Dies ist besonders auffällig, wenn Sie eine CSS-in-JS-Bibliothek zum Generieren von Selektoren verwenden, da das JavaScript-Bundle erst fertig ausgeführt werden muss, bevor Stile angewendet werden können.

Um dies zu verhindern, kann der wichtige CSS-Code oder die Mindestmenge an CSS, die zum Rendern der ersten Seite erforderlich ist, direkt in die <head> des HTML-Dokuments eingefügt werden. react-snap verwendet im Hintergrund eine weitere Drittanbieterbibliothek, minimalcss, um wichtige CSS für verschiedene Routen zu extrahieren. Um diese Funktion zu aktivieren, geben Sie Folgendes in der Datei package.json an:

"reactSnap": {
  "inlineCss": true
}

Wenn Sie einen Blick auf die Antwortvorschau in den Chrome-Entwicklertools werfen, sehen Sie nun die Seite mit dem benutzerdefinierten Stil mit wichtigen CSS-Inline-Elemente.

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 in Ihrer Anwendung keine serverseitigen Renderingrouten ausführen, verwenden Sie react-snap, um vorab statischen HTML-Code für Ihre Nutzer zu rendern.

  1. Installieren Sie es als Entwicklungsabhängigkeit und beginnen Sie nur mit den Standardeinstellungen.
  2. Verwende die experimentelle Option inlineCss, um wichtigen CSS-Code inline einzubetten, wenn sie für deine Website funktioniert.
  3. Wenn Sie die Codeaufteilung auf Komponentenebene innerhalb von Routen verwenden, dürfen Sie für Ihre Nutzer keinen Ladezustand vorab rendern. Weitere Informationen dazu finden Sie in der README-Datei zu react-snap.