Zusammenfassung der Schlüsselpunkte
Wenn Sie jemals eine grundlegende React -App -Seite erstellt haben, kann sie schlechte SEO- und Leistungsprobleme haben, insbesondere auf langsameren Geräten. Sie können traditionelle Webserver -Rendering hinzufügen (normalerweise mit NodeJS), dies ist jedoch kein einfacher Prozess, insbesondere bei der Behandlung asynchroner APIs.
Die beiden Hauptvorteile des serverseitigen Rendering-Codes sind:
Denken Sie daran, dass Google darauf wartet, dass Ihr JavaScript geladen wird, so dass sich einfache Inhalte wie den Titelinhalt ohne Probleme ändern. (Ich kann jedoch nicht sagen, was mit anderen Suchmaschinen passiert oder wie zuverlässig das ist.)
In diesem Artikel werde ich diskutieren, wie Sie Daten von einer asynchronen API erhalten, wenn Sie den Server-React-Code verwenden. React Code verfügt über eine gesamte Anwendungsstruktur in JavaScript. Dies bedeutet, dass Sie im Gegensatz zum herkömmlichen MVC -Modus mit Controllern nicht wissen, welche Daten Sie benötigen, bevor die Anwendung rendert. Mit einem Framework wie React-App erstellen können Sie schnell qualitativ hochwertige Arbeitsanwendungen erstellen. Sie müssen jedoch nur auf der Client-Seite verarbeiten. Dies hat Leistungsprobleme sowie SEO/Datenprobleme, bei denen Sie den Header nach Bedarf ändern können.
Frage
reagieren hauptsächlich das Rendering synchronisiert. Wenn Sie also keine Daten haben, wird der Ladebildschirm gerendert und auf die Ankunft der Daten warten. Dies funktioniert auf der Serverseite nicht gut, da Sie vor dem Rendern nicht wissen, was Sie benötigen, oder Sie wissen, was Sie brauchen, aber Sie haben es gemacht.
Zeigen Sie diese Standard -Rendering -Methode an:
ReactDOM.render( <provider> store={store}></provider> <browserrouter></browserrouter> <app></app> > > , document.getElementById('root') )
Frage:
Ich habe hier zwei Bibliotheken verwendet und sie sind sehr beliebt, daher kann es hoffentlich auf andere von Ihnen verwendete Bibliotheken angewendet werden.
Redux: Der Status des Speicherservers und der Client -Synchronisation ist ein Albtraumproblem. Es ist sehr teuer und führt oft zu komplexen Fehlern. Auf der Serverseite möchten Sie im Idealfall nichts mit Redux tun, außer dass es ausreicht, damit die Dinge funktionieren und richtig rendern. (Sie können es weiterhin wie gewohnt verwenden. Stellen Sie nur genug Status fest, damit es wie ein Kunde aussieht.) Wenn Sie es versuchen möchten, lesen Sie die verschiedenen verteilten Systemführer als Ausgangspunkt.
React-Router: FYI, dies ist die V4-Version, die die Standardversion ist, aber sie ist sehr unterschiedlich, wenn Sie ein älteres vorhandenes Projekt haben. Sie müssen sicherstellen, dass Sie das Routing auf der Serverseite und auf der Client -Seite verarbeiten und v4 verwenden - es ist in dieser Hinsicht hervorragend.
Was ist, wenn Sie einen Datenbankanruf tätigen müssen? Dies wird plötzlich zu einem großen Problem, da es asynchron ist und sich in Ihrer Komponente befindet. Dies ist natürlich keine neue Frage: Betrachten Sie sie im offiziellen React -Repository.
Sie müssen rendern, um festzustellen, welche Abhängigkeiten benötigt werden - diese Abhängigkeiten müssen zur Laufzeit festgelegt werden - und um diese Abhängigkeiten zu erhalten, bevor sie dem Kunden zur Verfügung gestellt werden.
vorhandene Lösungen
unten werde ich die derzeit bereitgestellten Lösungen für dieses Problem überprüfen.
Bevor wir beginnen, ist Next.js ideal für Sie, wenn Sie serverseitige React-Code oder universelle Anwendung für Ihre Produktionsumgebung wünschen. Es ist effektiv, prägnant und hat Zeit für Zeit.
Es ist jedoch der Meinung, dass Sie ihre Toolchain verwenden müssen, und die Art und Weise, wie sie mit asynchronem Datenladen umgehen, ist nicht unbedingt flexibel.
Diese direkte Kopie des Inhalts im nächsten.js Repository -Dokument anzeigen:
ReactDOM.render( <provider> store={store}></provider> <browserrouter></browserrouter> <app></app> > > , document.getElementById('root') )
getInitialProps
ist der Schlüssel, es wird ein Versprechen zurückgegeben, das sich auf ein mit Requisiten gefüllter Objekt entscheidet und nur auf der Seite ist. Das Beste von allen ist, dass dies nur in ihre Toolchain integriert ist: Fügen Sie es ohne Arbeit hinzu, um zu arbeiten!
Wie erhalten Sie Datenbankdaten? Sie machen einen API -Anruf. Du willst nicht? Ok, das ist schrecklich. (Okay, Sie können benutzerdefinierte Inhalte hinzufügen, müssen ihn jedoch selbst vollständig implementieren.) Wenn Sie darüber nachdenken, ist dies jedoch eine sehr vernünftige und allgemein gute Praxis und die Latenz auf dem Server ist fast vernachlässigbar.
Was Sie auch zugreifen können, ist begrenzt - fast nur das Anforderungsobjekt. Oh, und wenn Sie es noch nicht bemerkt haben, funktioniert es nur mit Seitenkomponenten auf der Spitze.
Redux Connect ist ein sehr eindeutiger Server-Seite mit einer schönen Idee, aber dies ist möglicherweise nicht für Sie, wenn Sie nicht alle Tools verwenden, die sie beschreiben. Dieses Paket enthält viele Inhalte, ist aber sehr komplex und wurde nicht auf den Reagieren von Router V4 aufgerüstet. Es gibt viele Einstellungen, aber schauen wir uns den wichtigsten Teil an, nur um einige Lektionen zu lernen:
ReactDOM.render( <provider> store={store}></provider> <browserrouter></browserrouter> <app></app> > > , document.getElementById('root') )
Dekorateure sind in JavaScript nicht Standard. Zum Zeitpunkt des Schreibens befinden sie sich in Phase 2, also verwenden Sie mit Vorsicht. Dies ist nur eine weitere Möglichkeit, Komponenten höherer Ordnung hinzuzufügen. Die Idee ist einfach: Der Schlüssel ist, was an Ihre Requisiten übergeben wird, und dann haben Sie eine Reihe von Versprechen, die analysieren und weitergeben. Das sieht gut aus. Vielleicht ist eine weitere Option Folgendes:
import React from 'react' export default class extends React.Component { static async getInitialProps ({ req }) { return req ? { userAgent: req.headers['user-agent'] } : { userAgent: navigator.userAgent } } render () { return <div> Hello World {this.props.userAgent} </div> } }
Dies kann mit JavaScript ohne allzu viele Probleme erfolgen.
Das React-Front-Load-Repository enthält nicht viele Dokumentationen oder Erklärungen, aber das beste Verständnis, das ich erhalten kann, kann aus dem Test (wie diesem) und dem Lesen des Quellcodees kommen. Wenn etwas montiert ist, wird es der Versprechen -Warteschlange hinzugefügt, und wenn die Warteschlange analysiert wird, wird es serviert. Was es tut ist sehr gut, obwohl es schwierig ist, etwas zu empfehlen, das nicht gut dokumentiert, gewartet oder verwendet wird:
// 1. 连接您的数据,类似于 react-redux @connect @asyncConnect([{ key: 'lunch', promise: ({ params, helpers }) => Promise.resolve({ id: 1, name: 'Borsch' }) }]) class App extends React.Component { render() { // 2. 将数据作为 props 访问 const lunch = this.props.lunch return ( <div>{lunch.name}</div> ) } }
Auf der Suche nach besseren Lösungen
Keine der oben genannten Lösungen entspricht wirklich zu meinen Erwartungen für die Flexibilität und Einfachheit der Bibliothek, daher werde ich nun meine eigene Implementierung einführen. Das Ziel ist nicht, Pakete zu schreiben, sondern Ihnen eine Vorstellung davon zu geben, wie Sie Ihre eigenen Pakete basierend auf Ihrem Anwendungsfall schreiben.
Das Repository dieser Beispiellösung befindet sich hier.
Die Idee dahinter ist relativ einfach, obwohl sie irgendwann eine Menge Code erzeugen wird. Dies soll die Ideen beschreiben, über die wir diskutieren.
Der Server muss den React -Code zweimal rendern, und wir werden dafür nur renderToString
verwenden. Wir wollen den Kontext zwischen dem ersten und dem zweiten Renderings halten. In unserem ersten Rendern haben wir versucht, API -Anrufe, Versprechen und asynchrone Operationen zu beseitigen. In unserem zweiten Render möchten wir alle Daten, die wir erhalten, in unseren Kontext zurücklegen und unsere Arbeitsseite für die Verteilung rendern. Dies bedeutet auch, dass der Anwendungscode Aktionen basierend auf dem Kontext (oder nicht der Ausführung von Vorgängen) ausführen muss, z. B. ob er sich auf dem Server oder auf dem Browser befindet, und in beiden Fällen, ob die Daten abgerufen werden.
Zusätzlich können wir es nach Bedarf anpassen. In diesem Fall ändern wir den Statuscode und den Header entsprechend dem Kontext.
In Ihrem Code müssen Sie wissen, ob Sie am Server oder auf dem Browser arbeiten. Idealerweise möchten Sie eine komplexe Kontrolle darüber. Mit React Router können Sie eine statische Kontext -Requisite erhalten, die großartig ist, also werden wir sie verwenden. Derzeit fügen wir nur ein Datenobjekt hinzu und fordern Daten an, wie wir von Next.js. Unsere APIs variieren zwischen Server und Client, sodass Sie eine Server -API bereitstellen müssen, die besser eine ähnliche Schnittstelle wie Ihre Client -API hat:
ReactDOM.render( <provider> store={store}></provider> <browserrouter></browserrouter> <app></app> > > , document.getElementById('root') )
Nach dem ersten Rendering werden wir diese anhängigen Versprechen erhalten und darauf warten, dass diese Versprechen abgeschlossen, dann erneut rendern, den Kontext aktualisieren:
import React from 'react' export default class extends React.Component { static async getInitialProps ({ req }) { return req ? { userAgent: req.headers['user-agent'] } : { userAgent: navigator.userAgent } } render () { return <div> Hello World {this.props.userAgent} </div> } }
Springen Sie schnell von unserem Server zum Anwendungscode: In einer unserer Komponenten mit Router -Verbindungen können wir ihn jetzt erhalten:
// 1. 连接您的数据,类似于 react-redux @connect @asyncConnect([{ key: 'lunch', promise: ({ params, helpers }) => Promise.resolve({ id: 1, name: 'Borsch' }) }]) class App extends React.Component { render() { // 2. 将数据作为 props 访问 const lunch = this.props.lunch return ( <div>{lunch.name}</div> ) } }
wow, es gibt viele komplizierte Code. In diesem Stadium möchten Sie möglicherweise einen weiteren Ansatz verfolgen, bei dem Sie den Datenabrufcode in eine andere Komponente trennen.
Diese Komponente besteht aus Komponenten, mit denen Sie möglicherweise vertraut sind - Schritte und componentWillMount
Schritte. Vierstufig, wenn Aussagen verschiedene Zustände behandeln-Prefetch-, Postfetch-, Pre-Render- und Back-End-Rendering. Wir fügen die Daten auch zum Header hinzu, nachdem sie geladen wurde.
Schließlich gibt es einen weiteren Schritt, um die Daten zu erhalten. Idealerweise haben Ihre API und Ihre Datenbank die gleiche API, was die Ausführung gleich macht. Möglicherweise möchten Sie diese in Aktionen in Thunk oder Saga aufnehmen, um sie skalierbarer zu machen.
Zeigen Sie den Artikel "Server React Rendering" und "Repository React Server Rendering" für weitere Informationen. Denken Sie daran, dass Sie den Zustand, in dem die Daten nicht geladen sind, noch verarbeiten müssen! Sie werden beim ersten Laden nur das Server-Side-Rendering durchführen, sodass Sie den Ladebildschirm auf nachfolgenden Seiten anzeigen.
Wir müssen alle vorgeholkten Daten als Teil der Seitenanforderung senden, damit wir ein Skript -Tag hinzufügen:
@asyncConnect([{ lunch: ({ params, helpers }) => Promise.resolve({ id: 1, name: 'Borsch' }) }])
Dann müssen wir es zu unserer Suche und unserem Austausch hinzufügen. HTML verwendet jedoch einen sehr grundlegenden Skript-Tag-Finder. Wenn Sie also Skript-Tags haben, müssen Sie es Basis-64 codieren. Vergiss auch nicht unsere Kopfetiketten!
const App = () => ( <frontload>isServer</frontload> <component1> entityId='1' store={store}></component1> > ) return frontloadServerRender(() => ( render(<app></app>) )).then((serverRenderedMarkup) => { console.log(serverRenderedMarkup) })
Wir verarbeiten auch Statuscodeänderungen - beispielsweise für 404 -, wenn Sie also eine 404 -Seite haben, können Sie dies tun:
const context = {data: {}, head: [], req, api} const store = configureStore() renderToString( <provider> store={store}></provider> <staticrouter> location={req.url} context={context}> <app></app> > > )
Zusammenfassung
Wenn Sie nicht sicher sind, was Sie tun, verwenden Sie einfach Next.js. Es ist für serverseitige Rendering und universelle Anwendungen ausgelegt. Wenn Sie die Flexibilität wünschen, alles manuell zu tun, können Sie es so tun, wie Sie es möchten. Zu einem Beispiel gehört möglicherweise, dass Sie Daten abrufen, die in einer untergeordneten Komponente abrufen, anstatt auf Seitenebene.
Ich hoffe, dieser Artikel kann Ihnen helfen, loszulegen! Vergessen Sie nicht, das Github -Repository für eine praktikable Implementierung zu überprüfen.
FAQs (FAQs) über asynchrone APIs und serverseitige Rendering React
serverseitiges Rendering (SSR) und clientseitiges Rendering (CSR) sind zwei verschiedene Möglichkeiten, Webseiten zu rendern. In SSR generiert der Server die vollständige HTML der Seite als Antwort auf die Anforderung und sendet sie dann an den Client. Dies führt zu schnelleren Ladezeiten der Anfangsseite und ist für SEO von Vorteil. Dies kann jedoch dazu führen, dass die Konvertierung von Seiten langsamer ist, da die gesamte Seite mit jeder Anfrage gerendert werden muss. CSR hingegen bedeutet, dass das Rendering im Browser mit JavaScript durchgeführt wird. Dies führt dazu, dass die anfängliche Ladezeit verlangsamt, aber die Seitenumwandlung ist schneller, da nur die erforderlichen Komponenten erneut gerendert werden müssen.
Um serverseitige Anfragen in einer clientseitigen React-Anwendung zu stellen, können Sie Bibliotheken wie API oder Axios abrufen. Sie können eine Anforderung in der componentDidMount
-Lifecycle -Methode oder im useEffect
-Haken stellen, wenn Sie die Funktionskomponente verwenden. Die Antwort kann dann auf den Zustand gesetzt und in Ihrer Komponente verwendet werden.
Dies kann auf die Art und Weise zurückzuführen sein, wie die Aktualisierung des Stapelstatus der Stapel reagiert. Wenn Sie globale Variablen innerhalb einer React -Komponente aktualisieren, kann dies aufgrund der asynchronen Natur von setState
zweimal aktualisiert werden. Um dies zu vermeiden, können Sie die Funktionsform von setState
verwenden, die sicherstellt, dass das Status -Update auf dem vorherigen Zustand basiert, nicht auf dem aktuellen Zustand.
Um die asynchrone API in serverseitiger React-React zu verwenden, können Sie die async/await
-Syntax im serverseitigen Code verwenden. Auf diese Weise können Sie auf die API -Antwort warten, bevor Sie die Seite rendern. Sie können Bibliotheken wie Axios verwenden, um API -Anfragen zu stellen.
serverseitiges Rendering hat viele Vorteile bei React. Es verbessert die Ladezeit der Anfangsseite, was zu einer besseren Benutzererfahrung führen kann. Es verbessert auch die SEO, da Suchmaschinencrawler die serverseitigen Inhalte leichter indexieren können. Darüber hinaus ermöglicht es einen konsistenten Ausgangszustand, da der gleiche Code sowohl auf dem Server als auch auf dem Client ausgeführt wird.
Sie können den try/catch
-Block verwenden, um Fehler in einer asynchronen Funktion zu verarbeiten. Auf diese Weise können Sie alle Fehler erfassen, die beim Erstellen von API -Anforderungen auftreten und angemessen umgehen, z. B. durch Wiedergabe von Fehlermeldungen.
Ja, Sie können Hooks in servergerenderten React verwenden. Denken Sie jedoch daran, dass Haken nur in Funktionskomponenten verwendet werden können, nicht in Klassenkomponenten. Außerdem werden einige Hooks (z. B. useEffect
) auf dem Server nicht ausgeführt. Sie müssen daher sicherstellen, dass Ihr Code diese Situation bearbeiten kann.
Es gibt viele Möglichkeiten, die Leistung von React -Anwendungen für das Serverwiedergabe zu verbessern. Sie können die Code -Segmentierung verwenden, um nur den erforderlichen Code für jede Seite zu laden. Sie können Cache auch verwenden, um die Wiederholung unveränderter Seiten zu vermeiden. Darüber hinaus kann das Optimieren des serverseitigen Codes dazu beitragen, die Leistung zu verbessern.
Sie können Testbibliotheken wie Scherz- und React-Testbibliothek verwenden, um Ihre serverseitigen React-Anwendungen zu testen. Diese Bibliotheken ermöglichen es Ihnen, Testkomponenten zu isolieren und sicherzustellen, dass sie korrekt rendern.
Ja, Next.js ist ein Framework für React, das das serverseitige Rendering außerhalb der Box unterstützt. Es bietet eine einfache serverseitige Rendering-API und unterstützt auch die statische Site-Generierung und das Client-Rendering.
Das obige ist der detaillierte Inhalt vonUmgang mit asynchronen APIs in servergerenderten React. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!