Analyse und Praxis des serverseitigen Rendering-Prinzips von React

Analyse und Praxis des serverseitigen Rendering-Prinzips von React

Die meisten Leute haben schon einmal vom Konzept des serverseitigen Renderings gehört, das wir SSR nennen. Viele Studenten haben in ihren Unternehmen möglicherweise bereits serverseitige Rendering-Projekte durchgeführt. Gängige Single-Page-Anwendungen wie Vue- oder React-Entwicklungsprojekte verwenden im Allgemeinen das clientseitige Rendering-Modell, das wir CSR nennen.

Dieses Modell bringt jedoch zwei offensichtliche Probleme mit sich. Das erste ist, dass die TTFP-Zeit relativ lang ist. TTFP bezieht sich auf die Anzeigezeit des ersten Bildschirms. Gleichzeitig erfüllt es nicht die Bedingungen für ein SEO-Ranking und das Ranking in den Suchmaschinen ist nicht sehr gut. Daher können wir einige Tools verwenden, um unser Projekt zu verbessern und die Einzelseitenanwendung in ein serverseitiges Rendering-Projekt umzuwandeln, sodass wir diese Probleme lösen können.

Die derzeit gängigen serverseitigen Rendering-Frameworks, auch als SSR-Frameworks bekannt, sind Nuxt.js für Vue und Next.js für React. Hier verwenden wir diese SSR-Frameworks nicht, sondern erstellen ein vollständiges SSR-Framework von Grund auf, um uns mit den zugrunde liegenden Prinzipien vertraut zu machen.

Schreiben von React-Komponenten auf dem Server

Wenn es sich um clientseitiges Rendern handelt, sendet der Browser zuerst eine Anforderung an den Browser, der Server gibt die HTML-Datei der Seite zurück, und dann sendet das HTML erneut eine Anforderung an den Server, der Server gibt die JS-Datei zurück und die JS-Datei wird im Browser ausgeführt, um die Seitenstruktur zu zeichnen und sie an den Browser zu rendern, um das Seiten-Rendering abzuschließen.

Beim serverseitigen Rendering läuft der Vorgang anders ab. Der Browser sendet eine Anfrage, der Server führt den React-Code aus, um die Seite zu generieren, und gibt die generierte Seite anschließend an den Browser zurück, der sie rendert. In diesem Fall ist der React-Code Teil des Servers und nicht des Frontends.

Hier demonstrieren wir den Code. Zuerst müssen Sie das Projekt mit npm init initialisieren und dann react, express, webpack, webpack-cli und webpack-node-externals installieren.

Wir schreiben zuerst eine React-Komponente. .src/components/Home/index.js. Da unser JS in der Knotenumgebung ausgeführt wird, müssen wir die CommonJS-Spezifikation befolgen und require und module.exports für Import und Export verwenden.

const React = erfordern('reagieren');

const Home = () => {
  zurück <div>nach Hause</div>
}

modul.exporte = {
  Standard: Startseite
};

Die Home-Komponente, die wir hier entwickelt haben, kann nicht direkt in Node ausgeführt werden. Wir müssen das Webpack-Tool verwenden, um die JSX-Syntax in JS-Syntax zu packen und zu kompilieren, damit NodeJS sie erkennen kann. Wir müssen eine Datei webpack.server.js erstellen.

Wenn Sie Webpack auf der Serverseite verwenden, müssen Sie ein Schlüssel-Wert-Paar mit Ziel als Knoten hinzufügen. Wir wissen, dass der Pfad, wenn er auf der Serverseite verwendet wird, nicht in JS gepackt werden muss. Wenn der Pfad auf der Browserseite verwendet wird, muss er in JS gepackt werden. Daher sind die JS, die auf der Serverseite und auf der Browserseite kompiliert werden müssen, völlig unterschiedlich. Beim Verpacken müssen wir Webpack also mitteilen, ob der serverseitige oder der browserseitige Code verpackt werden soll.

Die Einstiegsdatei ist die Startdatei unseres Knotens. Hier schreiben wir sie als ./src/index.js. Die Ausgabedatei heißt bundle und das Verzeichnis befindet sich im Build-Ordner des folgenden Verzeichnisses.

const Path = require('Pfad');
const NodeExternals = require('webpack-node-externals'); // Zum Ausführen von webpack auf dem Server muss NodeExternals ausgeführt werden, was verhindert, dass Node-Module wie Express in js gepackt werden.

modul.exporte = {
  Ziel: "Knoten",
  Modus: "Entwicklung",
  Eintrag: './src/server/index.js',
  Ausgabe: {
    Dateiname: „bundle.js“,
    Pfad: Pfad.resolve(__dirname, 'build')
  },
  Externe: [NodeExternals()],
  Modul: {
    Regeln:
      {
        Test: /.js?$/,
        Lader: 'babel-loader',
        ausschließen: /node_modules/,
        Optionen:
          Voreinstellungen: ['reagieren', 'Stage-0', ['Umgebung', {
            Ziele: {
              Browser: ['letzte 2 Versionen']
            }
          }]]
        }
      }
    ]
  }
}

Abhängige Module installieren

npm installiere Babel-Loader, Babel-Core, Babel-Preset-React, Babel-Preset-Stage-0, Babel-Preset-Env – Speichern

Als nächstes schreiben wir einen einfachen Dienst basierend auf dem Express-Modul. ./src/server/index.js

var express = erforderlich('express');
var app = express();
const Home = erfordern('../Komponenten/Home');
app.get('*', Funktion(erfordert, res) {
  res.send(`<h1>hallo</h1>`);
})

var server = app.listen(3000);

Führen Sie Webpack aus und verwenden Sie zur Ausführung die Konfigurationsdatei webpack.server.js.

webpack --config webpack.server.js

Nach dem Verpacken erscheint eine Datei „bundle.js“ in unserem Verzeichnis. Diese Datei ist der endgültige ausführbare Code, der durch unser Verpacken generiert wird. Wir können Node verwenden, um diese Datei auszuführen und einen Server auf Port 3000 zu starten. Wir können auf diesen Dienst zugreifen, indem wir 127.0.0.1:3000 aufrufen und die Browserausgabe „Hallo“ sehen.

Knoten ./build/bundile.js

Der obige Code wird vor der Ausführung mit webpack kompiliert, sodass er die ES-Modulspezifikation unterstützt und die Verwendung von CommonJS nicht mehr erzwingt.

src/Komponenten/Home/index.js

importiere React von „react“;

const Home = () => {
  zurück <div>nach Hause</div>
}

Standard-Homepage exportieren;

Wir können die Home-Komponente in /src/server/index.js verwenden. Hier müssen wir zuerst react-dom installieren und renderToString verwenden, um die Home-Komponente in eine Beschriftungszeichenfolge umzuwandeln. Natürlich müssen wir uns hier auf React verlassen, also müssen wir React einführen.

importiere Express von „Express“;
Home aus „../Components/Home“ importieren;
importiere React von „react“;
importiere { renderToString } von „react-dom/server“;

const app = express();
const Inhalt = renderToString(<Home />);
app.get('*', Funktion(erfordert, res) {
  res.send(`
    <html>
      <body>${Inhalt}</body>
    </html>
  `);
})

var server = app.listen(3000);

# Webpack neu verpacken --config webpack.server.js
# Führen Sie den Serviceknoten ./build/bundile.js aus

Zu diesem Zeitpunkt zeigt die Seite den Code unserer React-Komponente an.

Das serverseitige Rendering von React basiert auf virtuellem DOM und beschleunigt das erste Bildschirm-Rendering der Seite erheblich. Serverseitiges Rendering hat jedoch auch Nachteile. Beim clientseitigen Rendering wird der React-Code auf der Browserseite ausgeführt, was die Leistung der Browserseite des Benutzers beansprucht, während serverseitiges Rendering die Leistung der Serverseite beansprucht, da der React-Code auf dem Server ausgeführt wird. Dies beansprucht die Leistung des Servers erheblich, da React-Code viel Rechenleistung verbraucht.

Wenn Ihr Projekt keine SEO-Optimierung benötigt und die Zugriffsgeschwindigkeit Ihres Projekts bereits sehr schnell ist, empfiehlt es sich, die SSR-Technologie nicht zu verwenden, da ihre Kosten immer noch relativ hoch sind.

Nach jeder Änderung unseres obigen Codes müssen wir die Webpack-Verpackung erneut ausführen und den Server starten, was zu mühsam zum Debuggen ist. Um dieses Problem zu lösen, müssen wir die automatische Verpackung von Webpack durchführen und den Knoten neu starten. Wir fügen den Build-Befehl zu package.json hinzu und verwenden --watch, um Dateiänderungen für die automatische Verpackung zu überwachen.

{
  ...
  "Skripte": {
    "Build": "webpack --config webpack.server.js --watch"
  }
  ...
}

Das bloße Neuverpacken reicht nicht aus, wir müssen auch den Knotenserver neu starten. Hier müssen wir das Nodemon-Modul verwenden. Hier verwenden wir die globale Installation von Nodemon und fügen einen Startbefehl in die Datei package.json ein, um unseren Knotenserver zu starten. Verwenden Sie nodemon, um die Build-Datei zu überwachen, und führen Sie „node ./build/bundile.js“ nach jeder Änderung erneut aus. Die Anführungszeichen müssen hier beibehalten und nur übersetzt werden.

{
  ...
  "Skripte": {
    "Start": "nodemon --watch build --exec node \"./build/bundile.js\"",
    "Build": "webpack --config webpack.server.js --watch"
  }
  ...
}

Zu diesem Zeitpunkt starten wir den Server. Hier müssen wir die folgenden Befehle in zwei Fenstern ausführen, da nach dem Erstellen keine anderen Befehle zulässig sind.

npm-Ausführung erstellen
npm ausführen starten

Nachdem wir den Code geändert haben, wird die Seite jetzt automatisch aktualisiert.

Der obige Prozess ist jedoch immer noch etwas mühsam. Wir benötigen zwei Fenster, um Befehle auszuführen. Wir möchten, dass ein Fenster beide Befehle ausführt. Wir müssen ein Drittanbietermodul npm-run-all verwenden, das global installiert werden kann. Ändern Sie es dann in package.json.

Wir sollten in der Entwicklungsumgebung paketieren und debuggen. Wir erstellen einen dev-Befehl, führen darin npm-run-all aus, --parallel bedeutet parallele Ausführung und führen alle Befehle aus, die mit dev: beginnen. Wir fügen vor dem Start und dem Erstellen ein dev: hinzu. Wenn ich zu diesem Zeitpunkt den Server starten und auf Dateiänderungen warten möchte, kann ich einfach npm run dev ausführen.

{
  ...
  "Skripte": {
    "Entwickler": "npm-run-all --parallel Entwickler:**",
    "dev:start": "nodemon --watch build --exec node \"./build/bundile.js\"",
    "dev:build": "webpack --config webpack.server.js --watch"
  }
  ...
}

Was ist Isomorphismus?

Im folgenden Code binden wir beispielsweise ein Klickereignis an div und hoffen, dass beim Klicken eine Klickaufforderung angezeigt wird. Aber nach dem Ausführen werden wir feststellen, dass dieses Ereignis nicht gebunden ist, weil der Server das Ereignis nicht binden kann.

src/Komponenten/Home/index.js

importiere React von „react“;

const Home = () => {
  zurückgeben <div onClick={() => { alert('click'); }}>Startseite</div>
}

Standard-Homepage exportieren;

Im Allgemeinen rendern wir zuerst die Seite und führen dann denselben Code auf der Browserseite aus wie bei einem herkömmlichen React-Projekt, sodass das Klickereignis verfügbar ist.

Dies führt zum Konzept des Isomorphismus. Nach meinem Verständnis wird ein Satz React-Code einmal auf dem Server und erneut auf dem Client ausgeführt.

Isomorphismus kann das Problem ungültiger Klickereignisse lösen. Erstens kann der Server die Seite normal anzeigen, indem er sie einmal ausführt, und der Client kann das Ereignis binden, indem er es erneut ausführt.

Wir können beim Rendern der Seite eine index.js laden und app.use verwenden, um einen Zugriffspfad für statische Dateien zu erstellen, sodass für den Zugriff auf die index.js die Datei /public/index.js angefordert wird.

app.use(express.static('öffentlich'));

app.get('/', Funktion(req, res) {
  res.send(`
    <html>
      <Text>
        <div id="root">${Inhalt}</div>
        <script src="/index.js"></script>
      </body>
    </html>
  `);
})

öffentlich/index.js

console.log('öffentlich');

Aufgrund dieser Situation können wir den React-Code einmal im Browser ausführen. Wir erstellen hier ein neues /src/client/index.js. Fügen Sie den vom Client ausgeführten Code ein. Hier verwenden wir Hydrat statt Render im isomorphen Code.

importiere React von „react“;
importiere ReactDOM von „react-dom“;

Home aus „../Components/Home“ importieren;

ReactDOM.hydrate(<Home />, document.getElementById('root'));

Dann müssen wir auch eine Datei webpack.client.js im Stammverzeichnis erstellen. Die Eingabedatei ist ./src/client/index.js und die Exportdatei ist public/index.js.

const Path = require('Pfad');

modul.exporte = {
  Modus: "Entwicklung",
  Eintrag: './src/client/index.js',
  Ausgabe: {
    Dateiname: 'index.js',
    Pfad: Pfad.resolve(__dirname, 'public')
  },
  Modul: {
    Regeln:
      {
        Test: /.js?$/,
        Lader: 'babel-loader',
        ausschließen: /node_modules/,
        Optionen:
          Voreinstellungen: ['reagieren', 'Stage-0', ['Umgebung', {
            Ziele: {
              Browser: ['letzte 2 Versionen']
            }
          }]]
        }
      }
    ]
  }
}

Fügen Sie einen Befehl zum Verpacken des Clientverzeichnisses in der Datei package.json hinzu

{
  ...
  "Skripte": {
    "Entwickler": "npm-run-all --parallel Entwickler:**",
    "dev:start": "nodemon --watch build --exec node \"./build/bundile.js\"",
    "dev:build": "webpack --config webpack.server.js --watch",
    "dev:build": "webpack --config webpack.client.js --watch",
  }
  ...
}

Auf diese Weise kompilieren wir die Dateien, die der Client ausführt, wenn wir ihn starten. Bei einem erneuten Besuch der Seite können Sie die Veranstaltung binden.

Als nächstes organisieren wir den Code des obigen Projekts. In den obigen Dateien webpack.server.js und webpack.client.js gibt es viele Duplikate. Wir können das Plug-In webpack-merge verwenden, um die Inhalte zusammenzuführen.

webpack.base.js

modul.exporte = {
  Modul: {
    Regeln:
      {
        Test: /.js?$/,
        Lader: 'babel-loader',
        ausschließen: /node_modules/,
        Optionen:
          Voreinstellungen: ['reagieren', 'Stage-0', ['Umgebung', {
            Ziele: {
              Browser: ['letzte 2 Versionen']
            }
          }]]
        }
      }
    ]
  }
}

webpack.server.js

const Path = require('Pfad');
const NodeExternals = require('webpack-node-externals'); // Zum Ausführen von webpack auf dem Server muss NodeExternals ausgeführt werden, was verhindert, dass Node-Module wie Express in js gepackt werden.

const merge = erforderlich('webpack-merge');
const config = require('./webpack.base.js');

const serverConfig = {
  Ziel: "Knoten",
  Modus: "Entwicklung",
  Eintrag: './src/server/index.js',
  Ausgabe: {
    Dateiname: „bundle.js“,
    Pfad: Pfad.resolve(__dirname, 'build')
  },
  Externe: [NodeExternals()],
}

module.exports = merge(Konfiguration, Serverkonfiguration);

webpack.client.js

const Path = require('Pfad');
const merge = erforderlich('webpack-merge');
const config = require('./webpack.base.js');

const clientConfig = {
  Modus: "Entwicklung",
  Eintrag: './src/client/index.js',
  Ausgabe: {
    Dateiname: 'index.js',
    Pfad: Pfad.resolve(__dirname, 'public')
  }
};

module.exports = merge(Konfiguration, Clientkonfiguration);

Der auf dem Server ausgeführte Code wird in src/server platziert, und das im Browser ausgeführte JS wird in src/client platziert.

Dies ist das Ende dieses Artikels über die Analyse und Praxis des serverseitigen Renderings von React. Weitere relevante Inhalte zum serverseitigen Rendering von React finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird!

Das könnte Sie auch interessieren:
  • Detaillierte Erklärung der Methode des serverseitigen React-Renderings (Isomorphismus)
  • Detaillierte Erklärung des serverseitigen Renderings von React vom Einstieg bis zur Meisterschaft
  • Detaillierte Erklärung der perfekten Lösung für React Server-Side-Rendering
  • Verwenden von Node zum Erstellen einer serverseitigen Rendering-Architektur von reactSSR
  • Detaillierte Erklärung der Implementierung des React-Renderings auf dem Server
  • React Server-Side Rendering (Zusammenfassung)
  • Serverseitiges Rendering und isomorphe Implementierung von React

<<:  CentOS6.8 verwendet cmake zur Installation von MySQL5.7.18

>>:  Installation der virtuellen Maschine Kali Linux Vmware (Abbildung und Text)

Artikel empfehlen

WeChat-Miniprogramme ermöglichen nahtloses Scrollen

In diesem Artikelbeispiel wird der spezifische Co...

Gemeinsame Nutzung von zwei Plug-Ins zur Übersetzung von Webseiten

Übersetzen Sie diese URL: http://translateth.is G...

Implementierungscode des JQuery-Schrittfortschrittsachsen-Plug-Ins

Jeden Tag ein jQuery-Plugin - Schritt-Fortschritt...

Warum wird mir die Zugriffsschnittstelle für Docker Tomcat nicht angezeigt?

Frage: Kann der Ursprungsserver keine Darstellung...

So erstellen Sie ein Tomcat-Image basierend auf Dockerfile

Dockerfile ist eine Datei, die zum Erstellen eine...

MySQL-Gruppierungsabfragen und Aggregatfunktionen

Überblick Ich glaube, dass wir häufig auf solche ...

Vue implementiert rekursiv benutzerdefinierte Baumkomponenten

In diesem Artikel wird der spezifische Code der r...

Grafisches Tutorial zur Installation und Konfiguration von MySQL 5.7.18 winx64

Die Installation komprimierter Pakete hat sich se...

So führen Sie eine Spring Boot-Anwendung in Docker aus

In den letzten Tagen habe ich gelernt, wie man Sp...

Detaillierte Einführung in die Chrome-Entwicklertools - Zeitleiste

1. Übersicht Benutzer erwarten, dass die Webanwen...