React hat die Art und Weise, wie wir Benutzeroberflächen erstellen, durch die Einführung eines komponentenbasierten Designs, das Effizienz und Wiederverwendbarkeit fördert, völlig verändert. Die deklarative Methode und die komponentenbasierte Struktur haben unter Entwicklern an Beliebtheit gewonnen. Mit zunehmender Komplexität Ihrer Projekte könnten Sie jedoch aufgrund der Rendering- und Datenabrufmethoden auf Leistungsprobleme stoßen.
Bei den herkömmlichen Rendering-Methoden auf der Client-Seite sind Sie darauf angewiesen, dass der Browser JavaScript ausführt, um die erste Benutzeroberfläche anzuzeigen. Dies kann auf Geräten mit begrenzten Ressourcen zu Verzögerungen beim Laden führen. Das Abrufen von Daten von einer Anwendungsprogrammierschnittstelle (API) stellt eine zusätzliche Belastung für diese Geräte dar, was zu einer Verzögerung bei der Anzeige von Inhalten und zu weniger optimalen Benutzerinteraktionen führen kann.
Serverkomponenten bieten eine Lösung für diese Hindernisse, indem sie das Rendering von Komponenten auf dem Server ermöglichen. Dadurch kann der Server die Komponenten auf die Client-Seite streamen, was die Leistung und die Datenabrufprozesse verbessert, da die gesamte Verarbeitung auf dem Server und nicht auf den Geräten der Benutzer stattfindet.
In diesem Artikel erfahren Sie, wie sich die Rendering-Methoden von React im Laufe der Zeit entwickelt haben und welche Nachteile die Verwendung von React Suspense und Server-Side-Rendering (SSR) hat. Darüber hinaus erfahren Sie etwas über React Server Components (RSCs) und wie sie diese Probleme lösen.
Bevor Sie sich mit RSCs beschäftigen, ist es hilfreich, frühere Rendering-Strategien, wie React Suspense und SSR, zu verstehen.
React Suspense wurde eingeführt, um asynchrones Rendering in React-Anwendungen zu ermöglichen. Es erlaubt Komponenten, das Rendering "auszusetzen", bis bestimmte Bedingungen erfüllt sind, wie z.B. das Abrufen von Daten oder das Aufteilen von Code. Hier sind einige der Vorteile von Suspense:
React.lazy
zusammen, um Codeaufteilung zu ermöglichen und die Leistung zu verbessern, indem Komponenten nur dann geladen werden, wenn sie benötigt werden.React Suspense hat jedoch einige Einschränkungen, die bei der Skalierung Ihrer Anwendung zu beachten sind:
Suspense
und ErrorBoundary
verpacken, was zu wiederholtem Code führt und es schwieriger macht, alles konsistent und wartbar zu halten, wenn Ihre Anwendung wächst.Bei SSR werden die React-Komponenten auf dem Server gerendert und das vollständig generierte HTML wird dann zur Anzeige an die Clientseite gesendet. Im Gegensatz dazu werden bei RSCs die einzelnen Komponenten gerendert, wenn sie bereit sind, anstatt zu warten, bis die gesamte Anwendung geladen ist, wie es bei SSR der Fall ist. Dieser Ansatz hat mehrere Vorteile:
SSR hat aber auch Einschränkungen, die zu beachten sind:
RSCs sind ein neuer Komponententyp in React, der auf der Serverseite arbeitet, im Gegensatz zu traditionellen Komponenten, die auf der Clientseite arbeiten. Sie helfen dabei, die mit Suspense und konventionellen SSR verbundenen Probleme zu lösen, indem sie es ermöglichen, Komponenten zu verarbeiten und als HTML vom Server zum Client zu streamen. RSCs übernehmen auch den Datenabruf auf dem Server und stellen sicher, dass vertrauliche Informationen wie API-Schlüssel nicht an den Client weitergegeben werden.
RSCs bieten einige bedeutende Vorteile:
Im Vergleich zu clientseitigen Komponenten werden Ausführung, Datenverwaltung und Leistung bei RSCs anders gehandhabt.
Herkömmliche Komponenten werden im Browser (clientseitig) ausgeführt, wo JavaScript benötigt wird, um die Benutzeroberfläche (UI) anzuzeigen. RSCs werden auf dem Server ausgeführt, indem sie vorgerendertes HTML an das Client-Gerät senden, anstatt alles lokal zu verarbeiten. Dieser Ansatz verringert die Arbeitslast auf dem Gerät des Benutzers und verbessert die Ladegeschwindigkeit. Die serverseitige Verarbeitung von Layouts und statischen Inhalten ist auch ideal für nicht interaktive oder datengesteuerte Komponenten. Client-Komponenten können innerhalb von RSCs verschachtelt werden, wenn Interaktivität erforderlich ist, z. B. für Schaltflächen oder Formulare, während sensible Daten auf dem Server geschützt bleiben.
Herkömmliche Komponenten können die Größe des clientseitigen JavaScript-Bündels erhöhen, was zu einer langsameren Anwendungsleistung führen kann. RSCs erhöhen die Größe des Client-Pakets nicht, da sie auf der Serverseite arbeiten, was zu geringeren Downloads und schnelleren Ladezeiten führt. Sie können RSCs auch verwenden, um das Caching zu verbessern. Vom Server gerenderte Inhalte lassen sich leichter zwischenspeichern, was die Antwortzeiten für häufig abgerufene Daten, wie z. B. beliebte Produkte in einem Online-Shop, beschleunigt, ohne dass die Datenbank wiederholt abgefragt werden muss.
Um RSCs in Ihrem Projekt zu implementieren, führen Sie die folgenden Schritte aus, um Ihre Umgebung einzurichten und sowohl server- als auch clientseitige Komponenten effektiv zu nutzen.
Stellen Sie zunächst sicher, dass Sie die neueste Node.js-Version auf Ihrem Rechner installiert haben. Der erste Schritt besteht darin, ein neues React-Projekt von Ihrer Shell oder Ihrem Terminal aus zu erstellen:
npx create-react-app your-app --template cra-template-pwa cd your-app
Sobald Ihr Projekt initialisiert ist, installieren Sie die für die RSCs erforderlichen Abhängigkeiten:
npm install react@18 react-dom@18 babel-loader@8 @babel/preset-react webpack@5 webpack-cli
Weitere Informationen finden Sie in der offiziellen Dokumentation zu jeder dieser Bibliotheken: React, react-dom, webpack, Babel und webpack-cli.
Führen Sie den folgenden Befehl aus, um die Loader für CSS und Asset-Dateien wie SVGs zu installieren, die es Ihrer Anwendung ermöglichen, Stylesheets und Mediendateien zu verarbeiten und einzubinden:
npm install css-loader style-loader file-loader --save-dev
Richten Sie Babel ein, indem Sie im Stammverzeichnis Ihres Projekts eine .babelrc-Datei
mit folgendem Inhalt erstellen:
{ "presets": ["@babel/preset-react"] }
Erstellen Sie eine neue Datei namens webpack.config.js
im Stammverzeichnis Ihres Projekts und fügen Sie die folgende Konfiguration hinzu, um webpack einzurichten:
const path = require("path"); module.exports = [ // Server-seitige Konfiguration { entry: "./src/server.js", // Server-Einstiegspunkt target: "node", output: { path: path.resolve(__dirname, "dist"), filename: "server.js", }, module: { rules: [ { test: /\.jsx?$/, use: "babel-loader", exclude: /node_modules/, }, { test: /\.css$/, // Rule for CSS files use: ["style-loader", "css-loader"], }, { test: /\.(png|jpe?g|gif|svg)$/, // Regel für Bilddateien verwenden: ["file-loader"], }, ], }, resolve: { extensions: [".js", ".jsx"], }, }, // Client-seitige Konfiguration { entry: "./src/index.js", // Client-Einstiegspunkt target: "web", // Dies weist Webpack an, für die Browserausgabe zu bündeln: { path: path.resolve(__dirname, "dist"), filename: "client.js", // Client-seitiges Bundle }, module: { rules: [ { test: /\.jsx?$/, use: "babel-loader", exclude: /node_modules/, }, { test: /\.css$/, // Rule for CSS files use: ["style-loader", "css-loader"], }, { test: /\.(png|jpe?g|gif|svg)$/, // Regel für Bilddateien verwenden: ["file-loader"], }, ], }, resolve: { extensions: [".js", ".jsx"], }, }, ];
Nachdem webpack konfiguriert ist, können Sie nun eine Datei namens server.js
im src-Ordner
mit dem folgenden Code erstellen, um Ihren Server-Einstiegspunkt einzurichten:
import React from "react"; const express = require("express"); const ReactDOMServer = require("react-dom/server"); const App = require("./App").default; const app = express(); // Serve the static files from the 'dist' folder (where Webpack will put client.js) app.use(express.static("dist")); app.get("*", (req, res) => { const appHtml = ReactDOMServer.renderToString(<App />); res.send(` <!DOCTYPE html> <html lang="en"> <head><title>React Server Komponenten</title></head><body> <div id="root">${appHtml}</div> <!-- Einbinden des clientseitigen Bundles --> <script src="/client.js"></script> </body> </html> `); }); app.listen(3000, () => console.log("Server läuft auf Port 3000"));
Erstellen Sie im Ordner src
eine neue Datei mit dem Namen UserList.server.js
, um eine grundlegende Serverkomponente einzurichten, die Daten abruft:
import React from "react"; function UserList() { // Dummy-Array von Benutzern const users = [ { id: 1, name: "John Doe" }, { id: 2, name: "Jane Smith" }, { id: 3, name: "Alice Johnson" }, ]; return ( <ul> {users.map((user) => ( <li key={user.id}>{benutzer.name}</li> ))} </ul> ); } export default UserList;
Diese Komponente zeigt Benutzerdaten an und gibt eine HTML-Liste zurück. Um Client-seitige Interaktivität hinzuzufügen, erstellen Sie eine Datei namens Counter.client.js
im src-Verzeichnis
für Ihre Client-Komponente:
import React, { useState } from "react"; function Counter({ initialCount }) { const [count, setCount] = useState(initialCount); return ( <div><button onClick={() => {setCount((prevCount) => {const newCount = prevCount + 1;return newCount; });}} >Erhöhe 1 </button> <p>Zahl: {count}</p> </div> ); } export default Counter;
Auf diese Weise initialisiert der Server den Status, und der Client kümmert sich um die Interaktivität. Sie haben nun einen vollständigen Workflow für RSCs eingerichtet, eine Serverkomponente erstellt, Daten an eine Clientkomponente übergeben und die clientseitige Interaktivität aktiviert.
Als Nächstes aktualisieren Sie src/App.js
und fügen den folgenden Code ein, der sowohl die Server- als auch die Client-Komponente integriert:
import React from "react"; import UserList from "./UserList.server"; import Counter from "./Counter.client"; function App() { return ( <div> <h1>Benutzer</h1> <UserList /> <Counter initialCount={50} /> </div> ); } export default App;
Wenn der Server nun die App-Komponente rendert, wird er auch das UserList
Dashboard
als Serverkomponente rendern und den HTML-Code an den Client senden.
Um Ihren Server auszuführen, bündeln Sie den Code und starten Sie ihn:
npx webpack node dist/server.js
Wenn Sie diese Befehle ausführen, wird der Server auf Port 3000 ausgeführt
. An diesem Punkt rendert Ihre Anwendung React-Komponenten auf dem Client und dem Server!
Da RSCs den größten Teil des Renderings auf dem Server erledigen, kann die Verlagerung eines möglichst großen Teils des Renderings Ihrer Anwendung auf den Server die Leistung erheblich verbessern, während interaktive Funktionen bei Bedarf erhalten bleiben. Im Folgenden finden Sie einige Best Practices, die Ihnen dabei helfen können, dies zu erreichen und die Geschwindigkeit, Flexibilität und Verwaltbarkeit Ihrer Anwendung mit RSCs zu verbessern.
Erstens: Verwenden Sie RSCs, um Daten aus APIs oder Datenbanken abzurufen. Wenn Sie die Daten bereits auf dem Server abgerufen haben, sollten Sie sie nicht erneut auf dem Client abrufen. Wenn Sie z. B. Benutzerdaten auf dem Server laden und an den Client weitergeben, ist kein zweiter API-Aufruf auf der Client-Seite erforderlich, es sei denn, die Daten ändern sich.
Die Aufteilung des Codes in kleine Teile und das selektive Laden der benötigten Skripte mit Tools wie Vite oder webpack kann die Ladezeiten verbessern. Erstellen Sie Komponenten, die in Ihrer gesamten Anwendung wiederverwendet werden können. Wenn zum Beispiel mehrere Seiten eine Liste von Benutzern anzeigen müssen, erstellen Sie eine UserList-Komponente
, die überall funktioniert.
Schließlich sollten Sie die Server-Komponenten leichtgewichtig halten, indem Sie sie ausschließlich auf das Rendern von Daten konzentrieren, da sie nicht wie Client-Komponenten einen Zustand verwalten müssen. Konzentrieren Sie sich darauf, dass sie leichtgewichtig und nur für die Darstellung von Daten zuständig sind. Hydrieren Sie nur die Teile einer Seite, die interaktiv sein müssen. Wenn die Seite z. B. hauptsächlich statisch ist, aber ein Formular oder eine interaktive Schaltfläche enthält, sollten nur diese Komponenten hydratisiert werden.
Obwohl RSCs viele Vorteile bieten, ist es auch wichtig, die Hindernisse und Grenzen zu kennen, die mit ihrer Einbindung in Ihr Projekt verbunden sind.
Serverkomponenten können nicht mit Lebenszyklusmethoden wie useEffect
oder useState
interagieren. Das bedeutet, dass Sie die clientseitige Interaktivität nicht innerhalb von Serverkomponenten verwalten können. Wenn zum Beispiel ein Formular serverseitig gerendert wird, benötigen Sie eine Client-Komponente, um Eingabeänderungen in Echtzeit zu verarbeiten.
Wenn Sie in Ihren Projekten sowohl mit client- als auch mit serverseitigen Komponenten arbeiten, ist es wichtig, die Interaktion zwischen diesen beiden Komponententypen in Ihrer Anwendung zu verwalten, um Probleme zu vermeiden. Wenn Ihre Anwendung beispielsweise Daten vom Server abruft und die Benutzer diese Daten lokal auf ihren Geräten bearbeiten können, könnten Sie Probleme mit der Konsistenz der Daten zwischen dem Server und den clientseitigen Komponenten bekommen.
Serverkomponenten können nur serialisierbare Requisiten verwenden, d. h. Sie können keine Funktionen, Symbole oder komplexe Objekte übergeben, die nicht serialisiert werden können. Wenn Sie beispielsweise eine Callback-Funktion von einer Server-Komponente an eine Client-Komponente senden, führt dies zu einer Fehlermeldung. Serverseitige Komponenten haben keinen Zugriff auf Browser-APIs wie window
, document
oder localStorage
. Wenn Sie mit dem DOM interagieren müssen, muss dies in einer Client-Komponente geschehen.
Wenn das vom Server angezeigte HTML nicht mit dem übereinstimmt, was das clientseitige JavaScript erwartet, kann dies zu Problemen beim Hydrierungsprozess führen. Beispielsweise können Unterschiede in der Formatierung von Datumsangaben auf dem Server und auf dem Client zu subtilen Abweichungen führen. Hydrierungsfehler können schwer zu beheben sein, da die Ursache nicht immer offensichtlich ist.
Einige Bibliotheken von Drittanbietern funktionieren möglicherweise nicht gut mit RSCs, insbesondere solche, die stark von clientseitigen Rendering-Techniken oder browserspezifischen APIs abhängen. Bibliotheken wie react-router-dom
erfordern zum Beispiel clientseitiges Rendering. Möglicherweise müssen Sie einige Bibliotheken ersetzen oder anpassen, damit sie mit RSCs funktionieren.
Es gibt praktische Lösungen, die Sie implementieren können, um die Konsistenz zu wahren und häufige RSC-Probleme zu lösen.
Verwenden Sie Tools zur Zustandsverwaltung, die sowohl auf dem Server als auch auf dem Client funktionieren, wie Redux oder Zustand. Diese Bibliotheken ermöglichen es Ihnen, Ihren Zustand zu zentralisieren, sodass server- und clientseitige Komponenten auf dieselben Daten zugreifen können. So können Sie beispielsweise mit Redux einen globalen Zustand speichern, der für beide Seiten der Anwendung verfügbar ist.
Stellen Sie sicher, dass Sie einen Datenfluss zwischen Server und Client aufrechterhalten, indem Sie Kontext gemeinsam nutzen. Wenn Sie zum Beispiel Benutzerdaten zwischen Server- und Client-Komponenten verschieben, stellen Sie sicher, dass die Informationen zentral verwaltet werden, um Diskrepanzen zu vermeiden.
Erwägen Sie den Einsatz von Entwicklungstools oder Code-Linters, um nicht-serialisierbare Eigenschaften zu identifizieren, die Probleme mit RSCs verursachen könnten. So könnenbeispielsweise Tools wie ESLint so eingerichtet werden, dass sie Funktionsrequisiten erkennen, die von serverbasierten Komponenten übertragen werden.
Stellen Sie sicher, dass die Komponenten so umstrukturiert werden, dass die Props serialisiert werden können und keine Probleme mit SSR auftreten. Eine Möglichkeit, dies zu tun, besteht darin, bestimmte Operationen wie Event-Handler in Client-Komponenten zu verlagern. Wenn Sie z. B. eine Callback-Funktion von einer Serverkomponente übergeben, stellen Sie sicher, dass der Code so angepasst wird, dass die Operation in der Clientkomponente stattfindet, in der sie verwendet wird.
Die Behandlung von Hydrationsfehlern erfordert proaktive Test- und Debugging-Techniken:
Wenn die Software von Drittanbietern nicht mit den Serverkomponenten zusammenarbeitet, die für die Anforderungen Ihres Projekts erforderlich sind, sollten Sie alternative Optionen prüfen, die mit dem Server kompatibel sind. Wenn Sie eine Open-Source-Bibliothek für Ihr Projekt verwenden, sollten Sie darüber nachdenken, einen Beitrag zur Entwicklung der Bibliothek zu leisten, damit diese auch RSC unterstützt. Durch Ihren Beitrag können Sie Ihre eigene Anwendung verbessern und auch einen positiven Einfluss auf die breitere Gemeinschaft ausüben, die sich für ihre Arbeit auf dieselbe Bibliothek verlässt.
Wenn Sie diese Herausforderungen mit den richtigen Strategien angehen, können Sie die Einschränkungen der RSCs effizient umgehen und robuste, leistungsfähige Anwendungen erstellen.
In diesem Artikel haben wir die Rendering-Techniken von React erläutert. Wir haben React Suspense und SSR vorgestellt und eine ausführlichere Anleitung zu RSCs gegeben. Sie können RSCs verwenden, um die Leistung Ihrer Anwendung zu verbessern, indem Sie den Bedarf an clientseitiger JavaScript-Verarbeitung verringern und das Laden der ersten Seite beschleunigen.
Wenn Sie RSCs in Ihren Projekten ausprobieren möchten, müssen Sie zunächst die Komponenten in Ihrer Anwendung ermitteln, die von SSR profitieren würden. Dann können Sie RSC langsam in Ihre Codebasis einbauen.
Der Betrieb der Infrastruktur für SSR und Serverkomponenten kann komplex sein. Die Verwendung von Upsun, einer Platform as a Service (PaaS), vereinfacht die Bereitstellung und Skalierung Ihrer React-Anwendungen. Mit der integrierten Node. js-Unterstützung und der automatischen Skalierbarkeit kann Upsun Ihnen helfen, Verkehrsspitzen reibungslos zu bewältigen. Upsun bietet außerdem Überwachungs- und Sicherheitstools und ermöglicht es Ihnen, mehrere Anwendungen oder Microservices in verschiedenen Sprachen innerhalb eines einzigen Projektszu verwalten. Auf diese Weise können Sie sich auf die Entwicklung Ihrer React-Anwendung konzentrieren, während Upsun die Kerninfrastruktur verwaltet.