Door Rohit Kumar
Hier is wat we in deze tutorial gaan bouwen: een mooie React-kaart zoals deze.
In deze tutorial gaan we server-side rendering gebruiken om een HTML-respons te leveren wanneer een gebruiker of crawler een URL van een pagina opvraagt. Deze laatste verzoeken worden aan de client-zijde afgehandeld.
Waarom hebben we dit nodig?
Laat me u naar het antwoord leiden.
- Wat is het verschil tussen client-side rendering en server-side rendering?
- Cons of Rendering React on the Server
- Wanneer moet je Server Side Rendering gebruiken?
- SEO
- Verbeter de prestaties
- React Rendered on Server
- React Rendered on Client’s Browser
- Hoe werkt het? – (4 Eenvoudige Stappen)
- Gaan van start met het opzetten van onze App
- Waarom moeten we bronbestanden compileren?
- Kopieer voorgecodeerde & statische bestanden
- Serverzijde
- src/server.js
- 2. src/template.js
- De client-kant
- src/bundle.js
- src/client.js
- Het allemaal samenvoegen
- Index.js
- Build & Run
- Klaar om een React Pro te worden?
- Bedankt voor het lezen.
Wat is het verschil tussen client-side rendering en server-side rendering?
Bij client-side rendering downloadt uw browser een minimale HTML-pagina. Het rendert de JavaScript en vult de inhoud in.
Server-side rendering, aan de andere kant, rendert de React-componenten op de server. De uitvoer is HTML-inhoud.
U kunt deze twee combineren om een isomorfe app te maken.
Cons of Rendering React on the Server
- SSR kan de prestaties verbeteren als uw toepassing klein is. Maar het kan ook de prestaties verminderen als het zwaar is.
- Het verhoogt de responstijd (en het kan erger zijn als de server druk is).
- Het verhoogt de responsgrootte, wat betekent dat de pagina er langer over doet om te laden.
- Het verhoogt de complexiteit van de toepassing.
Wanneer moet je Server Side Rendering gebruiken?
Ondanks deze gevolgen van SSR, zijn er enkele situaties waarin je het kunt en moet gebruiken.
SEO
Elke website wil in zoekopdrachten verschijnen. Corrigeer me als ik het mis heb.
Helaas begrijpen crawlers van zoekmachines JavaScript nog niet.
Dit betekent dat ze een lege pagina zien, ongeacht hoe nuttig uw site is.
Velen zeggen dat Google’s crawler nu JavaScript rendert.
Om dit te testen, heb ik de app op Heroku ingezet. Dit is wat ik zag in de Google Search Console:
Een lege pagina.
Dit was de belangrijkste reden waarom ik server-side rendering heb onderzocht. Vooral als het een hoeksteenpagina is, zoals een landingspagina, blog, enzovoort.
Om te controleren of Google uw site rendert, gaat u naar:
Search Console Dashboard > Crawl > Fetch as Google. Voer de pagina URL of laat het leeg voor de homepage.
Selecteer FETCH EN RENDER. Eenmaal voltooid, klik om het resultaat te zien.
Verbeter de prestaties
In SSR, hangt de prestatie van de toepassing af van de middelen van de server en de snelheid van het netwerk van de gebruiker. Dit maakt het zeer nuttig voor inhoud zware sites.
Bijvoorbeeld, stel dat u een medium-price mobiele telefoon met trage internet snelheid. U probeert een site te openen die 4MB downloadt voordat u iets kunt zien.
Zou u in staat zijn om binnen 2-4 seconden iets op uw scherm te zien?
Zou u die site weer bezoeken?
Ik denk het niet.
Een andere grote verbetering is de First User Interaction Time. Dit is het verschil in tijd tussen het moment dat een gebruiker de URL aanklikt en het moment dat hij de inhoud ziet.
Hier is de vergelijking. Ik heb het getest op een ontwikkelings-Mac.
React Rendered on Server
De eerste interactietijd is 300 ms. Hydrate eindigt na 400 ms. De belastingsevent wordt ongeveer na 500 ms afgesloten. U kunt dit zien in de bovenstaande afbeelding.
React Rendered on Client’s Browser
De eerste interactietijd is 400 ms. De laadgebeurtenis wordt afgesloten na 470 ms.
Het resultaat spreekt voor zich. Er is een verschil van 100ms in de eerste gebruiker interactietijd voor zo’n kleine app.
Hoe werkt het? – (4 Eenvoudige Stappen)
- Maak een verse Redux Store op elk verzoek.
- Optioneel dispatch sommige acties.
- Haal de staat uit de Store en voer SSR.
- Verstuur de staat verkregen in de vorige stap samen met het antwoord.
We zullen de state gebruiken die in de response wordt doorgegeven voor het maken van de initiële state op client-side.
Voordat je aan de slag gaat, kloon/download het complete voorbeeld van Github en gebruik het als referentie.
Gaan van start met het opzetten van onze App
Opent u eerst uw favoriete editor en shell. Maak een nieuwe map voor uw applicatie. Laten we beginnen.
npm init --yes
Vul de details in. Nadat package.json
is gemaakt, kopieer de afhankelijkheden en scripts hieronder erin.
Installeer alle afhankelijkheden door het uitvoeren van:
npm install
U moet Babel en webpack configureren voor ons build script om te werken.
Babel transformeert ESM en react in Node en browser-begrepen code.
Maak een nieuw bestand .babelrc
en zet de regel hieronder erin.
{ "presets": }
webpack bundelt onze app en zijn afhankelijkheden in een enkel bestand. Maak een ander bestand webpack.config.js
met de volgende code erin:
const path = require('path');module.exports = { entry: { client: './src/client.js', bundle: './src/bundle.js' }, output: { path: path.resolve(__dirname, 'assets'), filename: ".js" }, module: { rules: }}
Het bouwproces voert twee bestanden uit:
-
assets/bundle.js
– pure client side app. -
assets/client.js
– client side companion voor SSR.
De src/
map bevat de broncode. De gecompileerde Babel bestanden gaan in views/
. views
directory wordt automatisch aangemaakt indien deze niet aanwezig is.
Waarom moeten we bronbestanden compileren?
De reden is het verschil in syntaxis tussen ESM & CommonJS. Tijdens het schrijven van React en Redux, we intensief gebruik van import en export in alle bestanden.
Helaas, ze werken niet in Node. Hier komt Babel om te redden. Het onderstaande script vertelt Babel om alle bestanden in de src
directory te compileren en het resultaat in views.
"babel": "babel src -d views",
Nu kan Node ze uitvoeren.
Kopieer voorgecodeerde & statische bestanden
Als je de repository al hebt gekloond, kopieer dan daaruit. Anders download je ssr-static.zip bestand van Dropbox. Pak het uit en bewaar deze drie mappen in je app directory. Hier is wat ze bevatten.
- React
App
en componenten bevindt zich insrc/components
. - Redux-bestanden in
src/redux/
. -
assets/ & media/
: Bevat statische bestanden zoalsstyle.css
en afbeeldingen.
Serverzijde
Maak twee nieuwe bestanden met de namen server.js
en template.js
binnen de src/
map.
src/server.js
De magie gebeurt hier. Dit is de code waar je naar op zoek was.
import React from 'react';import { renderToString } from 'react-dom/server';import { Provider } from 'react-redux';import configureStore from './redux/configureStore';import App from './components/app';module.exports = function render(initialState) { // Model the initial state const store = configureStore(initialState); let content = renderToString(<Provider store={store} ><App /></Provider>); const preloadedState = store.getState(); return { content, preloadedState };};
In plaats van onze app te renderen, moeten we het in een functie verpakken en exporteren. De functie accepteert de initiële staat van de applicatie.
Hier is hoe het werkt.
- Pass
initialState
aanconfigureStore()
.configureStore()
returns een nieuwe Store instantie. Houd het in destore
variabele. - Roep
renderToString()
methode, met onze App als input. Het rendert onze app op de server en retourneert de geproduceerde HTML. Nu, de variabelecontent
slaat de HTML. - Haal de staat uit Redux Store door het aanroepen van
getState()
opstore
. Bewaar het in een variabelepreloadedState
. - Return de
content
enpreloadedState
. We zullen deze doorgeven aan ons sjabloon om de uiteindelijke HTML-pagina te krijgen.
2. src/template.js
template.js
exporteert een functie. Deze neemt title
, state
en content
als invoer. Het injecteert ze in het sjabloon en retourneert het uiteindelijke HTML-document.
Om de status door te geven, koppelt het sjabloon state
aan window.__STATE__
binnen een <scri
pt> tag.
Nu kunt u state
aan de client-kant lezen door window.__STATE__
te benaderen.
We voegen ook de SSR companion assets/client.js
client-side applicatie toe in een andere script tag.
Als u de pure client-versie aanvraagt, zet het alleen assets/bundle.js
in de script-tag.
De client-kant
De client-kant is vrij eenvoudig.
src/bundle.js
Dit is hoe u de React en Redux Provider
wrap schrijft. Het is onze pure client-side app. Geen trucs hier.
import React from 'react';import { render } from 'react-dom';import { Provider } from 'react-redux';import configureStore from './redux/configureStore';import App from './components/app';const store = configureStore();render( <Provider store={store} > <App /> </Provider>, document.querySelector('#app'));
src/client.js
Kent u zich dat? Ja, er is niets speciaals behalve window.__STATE__.
Alles wat we hoeven te doen is de initiële staat uit window.__STATE__
halen en doorgeven aan onze configureStore()
functie als de initiële staat.
Laten we eens kijken naar ons nieuwe client-bestand:
import React from 'react';import { hydrate } from 'react-dom';import { Provider } from 'react-redux';import configureStore from './redux/configureStore';import App from './components/app';const state = window.__STATE__;delete window.__STATE__;const store = configureStore(state);hydrate( <Provider store={store} > <App /> </Provider>, document.querySelector('#app'));
Laten we eens kijken naar de wijzigingen:
- Vervang
render()
doorhydrate()
.hydrate()
is hetzelfde alsrender()
maar wordt gebruikt om elementen te hydrateren die doorReactDOMServer
worden weergegeven. Het zorgt ervoor dat de inhoud hetzelfde is op de server en de client. - Leest de status van het globale venster object
window.__STATE__
. Sla het op in een variabele en verwijder dewindow.__STATE__
. - Maak een nieuwe store met
state
als initialState.
Alles klaar hier.
Het allemaal samenvoegen
Index.js
Dit is het beginpunt van onze applicatie. Het behandelt verzoeken en templating.
Het verklaart ook een initialState
variabele. Ik heb het gemodelleerd met gegevens in het assets/data.json
-bestand. We zullen het doorgeven aan onze ssr()
functie.
Note: Tijdens het verwijzen naar een bestand dat binnen src/
staat vanuit een bestand buiten src/
, gebruik dan normaal require()
en vervang src/
door views/
. U kent de reden (Babel compile).
Routing
-
/
: Standaard server-rendered homepage. -
/client
: Zuiver client-side rendering voorbeeld. -
/exit
: Server stop knop. Alleen beschikbaar in development.
Build & Run
Het is tijd om onze applicatie te bouwen en te draaien. We kunnen dit doen met een enkele regel code.
npm run build && npm run start
Nu draait de applicatie op http://localhost:3000.
Klaar om een React Pro te worden?
Ik start een nieuwe serie vanaf volgende week maandag om je React vaardigheden te laten knallen, onmiddellijk.
Bedankt voor het lezen.
Als je het leuk en nuttig vindt, volg me dan op Twitter & Webflow.