- Funktionen
- Pricing

React hat die Art und Weise, wie wir Benutzeroberflächen erstellen, durch die Einführung eines komponentenbasierten Designs, das Effizienz und Wiederverwendbarkeit fördert, grundlegend verändert. Seine deklarative Methode und die komponentenbasierte Struktur haben bei Entwicklern große Beliebtheit erlangt. Doch wenn deine Projekte an Komplexität zunehmen, kannst du aufgrund von Rendering- und Datenabrufmethoden auf performance-Probleme stoßen.
Bei den traditionellen Methoden des clientseitigen Renderings bist du darauf angewiesen, dass der Browser JavaScript ausführt, um die anfängliche Benutzeroberfläche anzuzeigen. Dies kann auf Geräten mit begrenzten Ressourcen zu Verzögerungen beim Laden führen. Das Abrufen von Daten über eine Anwendungsprogrammierschnittstelle (API) belastet diese Geräte zusätzlich, was zu Verzögerungen bei der Anzeige von Inhalten und zu einer weniger als idealen Benutzerinteraktion führen kann.
Serverkomponenten bieten eine Lösung für diese Hindernisse, indem sie das Rendern von Komponenten auf dem Server ermöglichen. Dadurch kann der Server die Komponenten an die Client-Seite streamen, was die performance und die Datenabrufprozesse verbessert, da die gesamte Verarbeitung auf dem Server und nicht auf den Geräten der Nutzer stattfindet.
In diesem Artikel erfährst du, wie sich die Rendering-Methoden von React im Laufe der Zeit weiterentwickelt haben, sowie welche Nachteile die Verwendung von React Suspense und serverseitigem Rendering (SSR) mit sich bringt. Außerdem lernst du React Server Components (RSCs) kennen und erfährst, wie sie diese Probleme lösen.
Bevor wir uns mit RSCs befassen, 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 handhaben. Es ermöglicht Komponenten, das Rendering „auszusetzen“, bis bestimmte Bedingungen erfüllt sind, wie z. B. das Abrufen von Daten oder Code-Splitting. Hier sind einige der Vorteile von Suspense:
React.lazy“, um Code-Splitting zu ermöglichen und die performance zu verbessern, indem Komponenten nur dann geladen werden, wenn sie benötigt werden.React Suspense hat jedoch einige Einschränkungen, die du beim Skalieren deiner Anwendung beachten solltest:
Suspense` und `ErrorBoundary` einbündelst, was zu sich wiederholendem Code führt und es schwieriger macht, alles konsistent und wartbar zu halten, wenn deine App wächst.Bei SSR werden React-Komponenten auf dem Server gerendert, und der vollständig generierte HTML-Code wird dann zur Anzeige an den Client gesendet. Im Gegensatz dazu werden bei RSCs einzelne Komponenten gerendert, sobald sie bereit sind, anstatt wie bei SSR darauf zu warten, dass die gesamte Anwendung geladen ist. Dieser Ansatz hat mehrere Vorteile:
SSR hat jedoch auch Einschränkungen, die es zu beachten gilt:
RSCs sind eine neue Art von Komponenten in React, die auf der Serverseite arbeiten, im Gegensatz zu herkömmlichen Komponenten, die auf der Clientseite arbeiten. Sie helfen dabei, die mit Suspense und herkömmlichem 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 so sicher, dass vertrauliche Informationen, wie z. B. API-Schlüssel, dem Client nicht offengelegt werden.
RSCs bieten einige wesentliche Vorteile:
Im Vergleich zu clientseitigen Komponenten handhaben RSCs Ausführung, Datenverwaltung und performance auf unterschiedliche Weise.
Herkömmliche Komponenten laufen im Browser (clientseitig), wo JavaScript benötigt wird, um die Benutzeroberfläche (UI) anzuzeigen. RSCs laufen auf dem Server, indem sie vorgerendertes HTML an das Client-Gerät senden, anstatt alles lokal zu verarbeiten. Dieser Ansatz entlastet das Gerät des Nutzers und verbessert die Ladegeschwindigkeit. Die serverseitige Verarbeitung von Layouts und statischen Inhalten ist zudem ideal für nicht-interaktive oder datengesteuerte Komponenten. Client-Komponenten können in RSCs verschachtelt werden, wo Interaktivität benötigt wird, wie z. B. bei Schaltflächen oder Formularen, während sensible Daten sicher auf dem Server bleiben.
Herkömmliche Komponenten können die Größe des clientseitigen JavaScript-Bundles erhöhen, was zu einer langsameren Performance der App führen kann. RSCs vergrößern das Paket des Clients nicht, da sie serverseitig arbeiten, was zu weniger Downloads und schnelleren Ladezeiten führt. Du kannst RSCs auch nutzen, um das Caching zu verbessern. Serverseitig gerenderte Inhalte lassen sich leichter zwischenspeichern, was die Antwortzeiten für häufig aufgerufene Daten beschleunigt – wie zum Beispiel beliebte Produkte in einem Online-Shop –, ohne die Datenbank wiederholt abfragen zu müssen.
Um RSCs in deinem Projekt zu implementieren, befolge diese Schritte, um deine Umgebung einzurichten und sowohl serverseitige als auch clientseitige Komponenten effektiv zu nutzen.
Stelle zunächst sicher, dass du die neueste Version von Node.js auf deinem Rechner installiert hast. Der erste Schritt besteht darin, ein neues React-Projekt über deine Shell oder dein Terminal zu erstellen:
npx create-react-app your-app --template cra-template-pwa
cd your-appSobald dein Projekt initialisiert ist, installiere die für RSCs erforderlichen Abhängigkeiten:
npm install react@18 react-dom@18 babel-loader@8 @babel/preset-react webpack@5 webpack-cli
Weitere Informationen findest du in der offiziellen Dokumentation zu den einzelnen Bibliotheken: React, react-dom, webpack, Babel und webpack-cli.
Führe den folgenden Befehl aus, um die Loader für CSS- und Asset-Dateien wie SVGs zu installieren, damit deine Anwendung Stylesheets und Mediendateien verarbeiten und einbinden kann:
npm install css-loader style-loader file-loader --save-devRichte Babel ein, indem du eine .babelrc Datei im Stammverzeichnis deines Projekts mit folgendem Inhalt:
{
"presets": ["@babel/preset-react"]
}Erstelle eine neue Datei mit dem Namen webpack.config.js im Stammverzeichnis deines Projekts und füge die folgende Konfiguration hinzu, um Webpack einzurichten:
const path = require("path");
module.exports = [
// Server-side configuration
{
entry: "./src/server.js", // Server entry point
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)$/, // Rule for image files
use: ["file-loader"],
},
],
},
resolve: {
extensions: [".js", ".jsx"],
},
},
// Client-side configuration
{
entry: "./src/index.js", // Client entry point
target: "web", // This tells Webpack to bundle for the browser
output: {
path: path.resolve(__dirname, "dist"),
filename: "client.js", // Client-side 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)$/, // Rule for image files
use: ["file-loader"],
},
],
},
resolve: {
extensions: [".js", ".jsx"],
},
},
];Nachdem du webpack konfiguriert hast, kannst du nun eine Datei namens „server.js“ im Ordner „src“ mit dem folgenden Programmieren erstellen, um deinen 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 Components</title></head>
<body>
<div id="root">${appHtml}</div>
<!-- Include the client-side bundle -->
<script src="/client.js"></script>
</body>
</html>
`);
});
app.listen(3000, () => console.log("Server running on port 3000"));Erstelle im Ordner „src“ eine neue Datei namens „UserList.server.js“, um eine einfache Serverkomponente einzurichten, die Daten abruft:
import React from "react";
function UserList() {
// Dummy array of users
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}>{user.name}</li>
))}
</ul>
);
}
export default UserList;Diese Komponente zeigt Benutzerdaten an und gibt eine HTML-Liste zurück. Um clientseitige Interaktivität hinzuzufügen, erstelle eine Datei namens „Counter.client.js“ im Verzeichnis „src“ für deine 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;
});
}}
>
Increment 1
</button>
<p>Count: {count}</p>
</div>
);
}
export default Counter;Auf diese Weise initialisiert der Server den Status, und der Client übernimmt die Interaktivität. Du hast nun einen vollständigen Workflow für RSCs eingerichtet, eine Serverkomponente erstellt, Daten an eine Clientkomponente übergeben und clientseitige Interaktivität aktiviert.
Als Nächstes aktualisierst du „src/App.js“, um den folgenden Code einzufügen, 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>Users</h1>
<UserList />
<Counter initialCount={50} />
</div>
);
}
export default App;Wenn der Server nun die App-Komponente rendert, rendert er auch die „UserList“-Dashboarde als Serverkomponente und sendet den HTML-Code an den Client.
Um deinen Server auszuführen, bündle das Programm und starte es:
npx webpack
node dist/server.jsWenn du diese Befehle ausführst, wird Server running on port 3000 zurückgegeben. Zu diesem Zeitpunkt rendert deine App React-Komponenten sowohl auf dem Client als auch auf dem Server!
Da RSCs den Großteil der Darstellung auf dem Server übernehmen, kann die Verlagerung möglichst vieler Darstellungsaufgaben deiner App auf den Server die performance erheblich verbessern, während interaktive Features bei Bedarf erhalten bleiben. Im Folgenden findest du einige Best Practices, die dir dabei helfen können, dies zu erreichen und die Geschwindigkeit, Flexibilität und Verwaltbarkeit deiner Anwendung mit RSCs zu verbessern.
Erstens: Nutze RSCs, um Daten von APIs oder Datenbanken abzurufen. Wenn du Daten bereits auf dem Server abgerufen hast, rufe sie nicht erneut auf dem Client ab. Wenn du beispielsweise Benutzerdaten auf dem Server lädst und an den Client weitergibst, ist kein zweiter API-Aufruf auf der Client-Seite erforderlich, es sei denn, die Daten ändern sich.
Das Programmieren des Codes in kleine Teile und das selektive Laden der benötigten Skripte mit Tools wie Vite oder Webpack kann helfen, die Ladezeiten zu verbessern. Erstelle Komponenten, die in deiner gesamten App wiederverwendet werden können. Wenn zum Beispiel mehrere Seiten eine Liste von Benutzern anzeigen müssen, erstelle eine „UserList“-Komponente, die überall funktioniert.
Schließlich solltest du Serverkomponenten schlank halten, indem du sie rein auf das Rendern von Daten fokussierst, da sie keinen Status verwalten müssen wie Clientkomponenten. Konzentriere dich darauf, sie schlank zu gestalten und ausschließlich für das Rendern von Daten zuständig zu machen. Lade nur die Teile einer Seite, die interaktiv sein müssen. Wenn die Seite zum Beispiel größtenteils statisch ist, aber ein Formular oder eine interaktive Schaltfläche enthält, lade nur diese Komponenten.
Obwohl RSCs Vorteile bieten, ist es auch wichtig, die Hindernisse und Grenzen zu verstehen, die mit ihrer Einbindung in dein Projekt einhergehen.
Serverkomponenten können nicht mit Lebenszyklusmethoden wie „useEffect“ oder „useState“ interagieren. Das bedeutet, dass du clientseitige Interaktivität innerhalb von Serverkomponenten nicht verwalten kannst. Wenn beispielsweise ein Formular serverseitig gerendert wird, benötigst du eine Clientkomponente, um Eingabeänderungen in Echtzeit zu verarbeiten.
Wenn du in deinen Projekten sowohl mit client- als auch mit serverseitigen Komponenten arbeitest, ist es wichtig, die Interaktion zwischen diesen beiden Komponententypen in deiner Anwendung zu handhaben, um Probleme zu vermeiden. Wenn deine Anwendung beispielsweise Daten vom Server abruft und Benutzer diese Daten lokal auf ihren Geräten bearbeiten können, kann es zu Problemen kommen, die Daten zwischen dem Server und den clientseitigen Komponenten konsistent zu halten.
Serverkomponenten können nur serialisierbare Props verwenden, was bedeutet, dass du keine Funktionen, Symbole oder komplexe Objekte übergeben kannst, die nicht serialisiert werden können. Wenn du beispielsweise eine Callback-Funktion von einer Serverkomponente an eine Clientkomponente sendest, führt dies zu einer Fehlermeldung. Serverseitige Komponenten haben keinen Zugriff auf Browser-APIs wie window, document oder localStorage. Wenn du mit dem DOM interagieren musst, muss dies in einer Clientkomponente geschehen.
Wenn das vom Server angezeigte HTML nicht mit den Erwartungen des clientseitigen JavaScripts übereinstimmt, kann dies zu Problemen während des Hydration-Prozesses führen. Beispielsweise können Unterschiede in der Formatierung von Datumsangaben auf dem Server im Vergleich zum Client zu subtilen Abweichungen führen. Hydration-Abweichungen können schwer zu debuggen 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 beispielsweise react-router-dom erfordern clientseitiges Rendering. Möglicherweise musst du einige Bibliotheken ersetzen oder anpassen, damit sie mit RSCs funktionieren.
Es gibt praktische Lösungen, die du implementieren kannst, um Konsistenz zu gewährleisten und häufige RSC-Probleme zu beheben.
Verwende Tools zur Zustandsverwaltung, die sowohl auf dem Server als auch auf dem Client funktionieren, wie Redux oder Zustand. Mit diesen Bibliotheken kannst du deinen Zustand zentralisieren, sodass servergerenderte Komponenten und clientseitige Komponenten auf dieselben Daten zugreifen können. Du könntest beispielsweise Redux verwenden, um einen globalen Zustand zu speichern, der beiden Seiten der App zur Verfügung steht.
Stelle sicher, dass du den Datenfluss zwischen Server und Client durch die gemeinsame Nutzung des Kontexts aufrechterhältst. Achte beispielsweise beim Austausch von Benutzerdaten zwischen Server- und Client-Komponenten darauf, dass die Informationen zentral verwaltet werden, um Diskrepanzen zu vermeiden.
Erwäge den Einsatz von Entwicklungstools oder Code-Lintern, um nicht serialisierbare Eigenschaften zu identifizieren, die Probleme mit RSCs verursachen könnten. Tools wie ESLint können beispielsweise so eingerichtet werden, dass sie Funktions-Props erkennen, die von serverbasierten Komponenten übertragen werden.
Achte darauf, Komponenten umzugestalten, um sicherzustellen, dass Props serialisiert werden können, und um Probleme mit SSR zu vermeiden. Eine Möglichkeit hierfür ist, bestimmte Vorgänge wie Event-Handler in Client-Komponenten zu verlagern. Wenn du beispielsweise eine Callback-Funktion von einer Serverkomponente übergibst, stelle sicher, dass der Code so angepasst wird, dass der Vorgang innerhalb der Client-Komponente stattfindet, in der er verwendet wird.
Das Beheben von Hydration-Mismatches erfordert proaktive Test- und Debugging-Techniken:
Wenn Software von Drittanbietern nicht wie für die Anforderungen deines Projekts erforderlich mit Serverkomponenten zusammenarbeitet, suche nach alternativen Optionen, die serverkompatibel sind. Wenn du für dein Projekt eine open source-Bibliothek verwendest, solltest du darüber nachdenken, etwas zurückzugeben, indem du zu ihrer Entwicklung beiträgst, um auch RSC-Unterstützung einzubauen. Durch deinen Beitrag kannst du deine eigene Anwendung verbessern und gleichzeitig einen positiven Einfluss auf die breitere Community ausüben, die für ihre Arbeit auf dieselbe Bibliothek angewiesen ist.
Indem du diese Herausforderungen mit geeigneten Strategien angehst, kannst du die Einschr änkungen von RSCs effizient umgehen und robuste, leistungsstarke Anwendungen erstellen.
In diesem Artikel haben wir die Rendering-Techniken von React erläutert. Wir haben React Suspense und SSR vorgestellt und einen tiefergehenden Leitfaden zu RSCs bereitgestellt. Du kannst RSCs nutzen, um die performance deiner Anwendung zu verbessern, indem du den Bedarf an clientseitiger JavaScript-Verarbeitung verringerst und das anfängliche Laden der Seiten beschleunigst.
Wenn du RSCs in deinen Projekten ausprobieren möchtest, besteht der erste Schritt darin, die Komponenten in deiner App zu identifizieren, die von SSR profitieren würden. Anschließend kannst du RSCs schrittweise in deinen Code integrieren.
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 deiner React-Anwendungen. Mit seiner integrierten Node.js-Unterstützung und automatischen Skalierbarkeit kann Upsun dir helfen, Traffic-Spitzen reibungslos zu bewältigen. Es bietet außerdem Überwachungs- und Sicherheitstools und ermöglicht es dir, mehrere Anwendungen oder Microservices in verschiedenen Sprachen innerhalb eines einzigen Projekts zu verwalten. Auf diese Weise kannst du dich auf die Entwicklung deiner React-Anwendung konzentrieren, während Upsun die Kerninfrastruktur übernimmt.
