Aufbau eines grundlegenden React SSR-Frameworks von Grund auf
Grace Collins
Solutions Engineer · Leapcell

Einführung in Server-Side Rendering mit React
In der dynamischen Landschaft der Webentwicklung sind Benutzererfahrung und Suchmaschinenoptimierung (SEO) von größter Bedeutung. Moderne Single-Page-Anwendungen (SPAs), die mit Bibliotheken wie React erstellt wurden, bieten reichhaltige interaktive Erlebnisse, stehen jedoch oft vor Herausforderungen bei der Leistung beim ersten Laden und der Indizierung durch Suchmaschinen. Hier kommt Server-Side Rendering (SSR) ins Spiel. SSR ermöglicht es uns, React-Komponenten auf dem Server in statisches HTML zu rendern und vollständig gestaltete Seiten an den Client zu senden. Dieser Ansatz verbessert die wahrgenommene Ladezeit erheblich, da Benutzer sofort Inhalte sehen, und bietet eine durchsuchbare HTML-Struktur, die Suchmaschinen bevorzugen. Dieser Artikel führt Sie durch den Prozess des Erstellens eines einfachen, aber funktionsfähigen React SSR-Frameworks von Grund auf, entmystifiziert die zugrunde liegenden Mechanismen und befähigt Sie, seine Vorteile zu nutzen.
Kernkonzepte von SSR verstehen
Bevor wir mit der Implementierung beginnen, wollen wir ein klares Verständnis der Schlüsselkonzepte von React SSR schaffen.
React-Komponenten
Das Herzstück jeder React-Anwendung sind Komponenten. Dies sind wiederverwendbare, in sich geschlossene UI-Teile, die mit JSX geschrieben werden. Für SSR werden dieselben Komponenten auf dem Server gerendert.
ReactDOMServer
Dies ist ein entscheidendes Paket von React, mit dem Sie React-Komponenten in statische HTML-Zeichenfolgen rendern können. Insbesondere renderToString
und renderToStaticMarkup
sind die Funktionen, auf die wir uns verlassen werden. renderToString
wird im Allgemeinen bevorzugt, da es data-reactid-Attribute enthält, die es React ermöglichen, die Komponente serverseitig zu "hydrieren" und sie interaktiv zu machen, ohne die gesamte DOM neu zu rendern.
Client-seitige Hydration
Nachdem der Server das HTML gesendet hat, "hängt" sich der clientseitige React-Code an dieses vorgerenderte HTML an. Dieser Prozess, bekannt als Hydration, transformiert das statische HTML in eine vollständig interaktive React-Anwendung, wobei die serverseitig gerenderte DOM-Struktur erhalten bleibt und ein Flackern oder Neurendern vermieden wird.
Express.js
Ein minimalistisches Web-Framework für Node.js, Express.js, dient als unser Server, der HTTP-Anfragen bearbeitet, unsere React-Anwendung rendert und das resultierende HTML an den Client zurücksendet.
Babel
Da wir unsere React-Komponenten mit JSX und möglicherweise modernen JavaScript-Funktionen schreiben werden, ist Babel unerlässlich, um unseren Code in ein Format zu transpilieren, das Node.js und clientseitige Browser verstehen können.
Aufbau eines minimalistischen React SSR-Frameworks
Lassen Sie uns mit dem schrittweisen Aufbau unseres SSR-Frameworks beginnen.
Projekt-Setup
Erstellen Sie zunächst ein neues Projektverzeichnis und initialisieren Sie es:
mkdir react-ssr-framework cd react-ssr-framework npm init -y
Installieren Sie als Nächstes die erforderlichen Abhängigkeiten:
npm install react react-dom express @babel/core @babel/preset-env @babel/preset-react babel-loader webpack webpack-node-externals npm install --save-dev nodemon
Wir benötigen zwei separate Babel-Konfigurationen: eine für den Server (der Node.js-Funktionen verwendet und sich nicht so sehr um Browserkompatibilität kümmern muss) und eine für den Client. Der Einfachheit halber verwenden wir in diesem Beispiel eine einzige .babelrc
für beide, um die Browserkompatibilität für clientseitigen Code sicherzustellen.
Erstellen Sie eine .babelrc
-Datei:
{ "presets": ["@babel/preset-env", "@babel/preset-react"] }
Unsere erste React-Komponente
Erstellen wir eine einfache App.js
-Komponente, die sowohl auf dem Server als auch auf dem Client gerendert wird.
// src/components/App.js import React from 'react'; const App = ({ message }) => { return ( <div> <h1>Hallo von React SSR!</h1> <p>{message}</p> <button onClick={() => alert('Dies ist ein interaktiver Button!')}> Klick mich </button> </div> ); }; export default App;
Serverseitige Rendering-Logik
Nun richten wir unseren Server mit Express.js ein, um unsere App
-Komponente zu rendern.
// src/server/index.js import express from 'express'; import React from 'react'; import ReactDOMServer from 'react-dom/server'; import App from '../components/App'; const app = express(); app.get('/', (req, res) => { const initialProps = { message: 'Dieser Inhalt wurde auf dem Server gerendert!' }; const appString = ReactDOMServer.renderToString(<App {...initialProps} />); res.send(` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>React SSR App</title> </head> <body> <div id="root">${appString}</div> <script> window.__INITIAL_PROPS__ = ${JSON.stringify(initialProps)}; </script> <script src="/client_bundle.js"></script> </body> </html> `); }); const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log(`Server lauscht auf Port ${PORT}`); });
Beachten Sie einige wichtige Details:
- Wir verwenden
ReactDOMServer.renderToString
, um die HTML-Zeichenfolge zu erhalten. - Wir betten die
appString
direkt in die HTML-Antwort ein. window.__INITIAL_PROPS__
ist eine globale Variable, die dieselben Props enthält, die für das serverseitige Rendering verwendet wurden. Dies ist entscheidend für die clientseitige Hydration.script src="/client_bundle.js"
gibt an, dass wir ein clientseitiges JavaScript-Bundle bereitstellen werden.
Client-seitige Hydration
Das clientseitige Bundle ist für die Hydration unserer Anwendung zuständig.
// src/client/index.js import React from 'react'; import ReactDOM from 'react-dom'; import App from '../components/App'; // Holen Sie sich die vom Server gesendeten initialen Props const initialProps = window.__INITIAL_PROPS__; ReactDOM.hydrate(<App {...initialProps} />, document.getElementById('root'));
Hier wird anstelle von ReactDOM.render
ReactDOM.hydrate
verwendet. hydrate
weist React an, zu versuchen, sich an das vorhandene HTML-Markup anzuhängen, anstatt alles neu zu rendern.
Bündelung mit Webpack
Wir müssen unser clientseitiges JavaScript bündeln, das dem Browser zur Verfügung gestellt werden soll. Wir müssen auch unseren serverseitigen Code kompilieren, da Node.js JSX oder ES-Module für import
/export
ohne Vorverarbeitung nicht nativ versteht.
Erstellen Sie eine webpack.config.js
-Datei:
// webpack.config.js const path = require('path'); const nodeExternals = require('webpack-node-externals'); const clientConfig = { mode: 'development', entry: './src/client/index.js', output: { path: path.resolve(__dirname, 'public'), filename: 'client_bundle.js', }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader', }, }, ], }, }; const serverConfig = { mode: 'development', target: 'node', // Entscheidend für Server-Bundles externals: [nodeExternals()], // Verhindert das Bündeln von node_modules-Abhängigkeiten entry: './src/server/index.js', output: { path: path.resolve(__dirname, 'build'), filename: 'server_bundle.js', }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader', }, }, ], }, }; module.exports = [clientConfig, serverConfig];
Wir haben zwei Konfigurationen: clientConfig
bündelt unseren clientseitigen Code in public/client_bundle.js
, und serverConfig
bündelt unseren serverseitigen Code in build/server_bundle.js
. Das target: 'node'
und externals: [nodeExternals()]
in serverConfig
sind für eine Node.js-Umgebung wichtig.
Bereitstellung statischer Assets
Unser Server muss das clientseitige Bundle bereitstellen. Fügen Sie eine Zeile zu src/server/index.js
vor der app.get
-Route hinzu:
// src/server/index.js (fügen Sie diese Zeile hinzu) app.use(express.static('public')); // Statische Dateien aus dem Verzeichnis 'public' bereitstellen
npm-Skripte
Fügen Sie Skripte zu Ihrer package.json
hinzu, um die Anwendung zu erstellen und auszuführen:
// package.json { "name": "react-ssr-framework", // ... andere Felder "scripts": { "build:client": "webpack --config webpack.config.js --env.target=client", "build:server": "webpack --config webpack.config.js --env.target=server", "build": "webpack --config webpack.config.js", "start": "node ./build/server_bundle.js", "dev": "npm run build && nodemon --watch build --exec \"npm start\"" }, // ... andere Felder }
Führen Sie nun npm run build
aus, um die anfänglichen Bundles zu erstellen, und dann npm run dev
, um den Server mit Auto-Neustarts bei Änderungen am Server-Bundle zu starten.
Testen des SSR
Navigieren Sie in Ihrem Browser zu http://localhost:3000
. Sie sollten "Hallo von React SSR!" und "Dieser Inhalt wurde auf dem Server gerendert!" sehen. Wichtig ist, wenn Sie den Quelltext der Seite anzeigen (nicht das Element inspizieren), finden Sie das React-HTML direkt in der Quelle eingebettet, was serverseitiges Rendering bestätigt. Der Button sollte ebenfalls interaktiv sein und die clientseitige Hydration demonstrieren.
Anwendungsfälle für SSR
Dieses grundlegende Framework zeigt zwar die Kernprinzipien, die in verschiedenen Szenarien angewendet werden können:
- Verbesserte SEO: Suchmaschinen-Crawler können das vorgerenderte HTML leicht parsen, was zu einer besseren Indizierung und einem besseren Ranking führt.
- Schnellere Erstladung: Benutzer sehen schnell aussagekräftige Inhalte, was die wahrgenommene Leistung verbessert und die Absprungrate reduziert.
- Bessere Zugänglichkeit: Das anfängliche HTML ist sofort verfügbar, was für Benutzer mit langsameren Internetverbindungen oder älteren Geräten von Vorteil sein kann.
- Open Graph-Tags und soziale Freigabe: Spezifische Metadaten für die Freigabe in sozialen Medien (z. B. og
, og) können auf dem Server dynamisch basierend auf dem spezifischen Seiteninhalt gerendert werden.
Fazit
Wir haben erfolgreich ein rudimentäres React SSR-Framework erstellt, das das wichtige Zusammenspiel zwischen React-Komponenten, ReactDOMServer für serverseitiges Rendering, Express.js für die Bereitstellung und clientseitiger Hydration veranschaulicht. Diese Einrichtung wandelt eine statische anfängliche Ansicht in eine interaktive Anwendung um und bietet ein grundlegendes Verständnis dafür, wie Leistung und SEO für React-Anwendungen verbessert werden können. Indem wir HTML auf dem Server rendern und es dann auf dem Client hydrieren, liefern wir eine überlegene Benutzererfahrung und begeistern Suchmaschinen-Algorithmen, was SSR zu einem Eckpfeiler der modernen, leistungsstarken Webentwicklung macht.