Af Rohit Kumar
Der er, hvad vi vil bygge i denne vejledning: et flot React-kort som dette.
I denne vejledning bruger vi server-side rendering til at levere et HTML-svar, når en bruger eller en crawler rammer en side-URL. Vi håndterer sidstnævnte anmodninger på klientsiden.
Hvorfor har vi brug for det?
Lad mig guide dig til svaret.
- Hvad er forskellen mellem client-side rendering og server-side rendering?
- Cons of Rendering React on the Server
- Hvornår skal du bruge Server Side Rendering?
- SEO
- Forbedre ydeevnen
- React Rendered on Server
- React Rendered on Client’s Browser
- Hvordan virker det? – (4 enkle trin)
- Kom i gang ved at opsætte vores app
- Hvorfor skal vi kompilere kildefilerne?
- Kopiering af prækodede & statiske filer
- Server Side
- src/server.js
- 2. src/template.js
- Klientsiden
- src/bundle.js
- src/client.js
- Sammensætning af det hele
- Index.js
- Build & Run
- Er du klar til at blive React Pro?
- Tak for at du læste dette.
Hvad er forskellen mellem client-side rendering og server-side rendering?
I client-side rendering downloader din browser en minimal HTML-side. Den renderer JavaScript og fylder indholdet i den.
Server-side rendering renderer på den anden side React-komponenterne på serveren. Outputtet er HTML-indhold.
Du kan kombinere disse to for at skabe en isomorf app.
Cons of Rendering React on the Server
- SSR kan forbedre ydeevnen, hvis din applikation er lille. Men det kan også forringe ydeevnen, hvis den er tung.
- Det øger svartiden (og det kan være værre, hvis serveren har travlt).
- Det øger svarstørrelsen, hvilket betyder, at det tager længere tid at indlæse siden.
- Det øger kompleksiteten af applikationen.
Hvornår skal du bruge Server Side Rendering?
Trods disse konsekvenser af SSR er der nogle situationer, hvor du kan og bør bruge det.
SEO
Alle websteder ønsker at blive vist i søgninger. Ret mig, hvis jeg tager fejl.
Det er desværre sådan, at søgemaskinernes crawlere endnu ikke forstår/render JavaScript.
Det betyder, at de ser en tom side, uanset hvor nyttigt dit websted er.
Mange folk siger, at Googles crawler nu render JavaScript.
For at teste dette har jeg implementeret appen på Heroku. Her er, hvad jeg så på Google Search Console:
En tom side.
Dette var den største grund til, at jeg udforskede server-side rendering. Især når det er en hjørnestenen side som f.eks. en landingsside, blog osv.
For at verificere, om Google renderer dit websted, skal du besøge:
Search Console Dashboard > Crawl > Fetch as Google. Indtast sidens URL-adresse, eller lad den være tom for forsiden.
Vælg FETCH AND RENDER. Når du er færdig, skal du klikke for at se resultatet.
Forbedre ydeevnen
I SSR afhænger applikationens ydeevne af serverens ressourcer og brugerens netværkshastighed. Dette gør det meget nyttigt for indholdstunge websteder.
Sig f.eks. at du har en mobiltelefon til mellemprisen med langsom internethastighed. Du forsøger at få adgang til et websted, der downloader 4 MB data, før du kan se noget.
Vil du kunne se noget på skærmen inden for 2-4 sekunder?
Vil du besøge det websted igen?
Det tror jeg ikke, du ville.
En anden stor forbedring er i første brugerinteraktionstid. Dette er forskellen i tid, fra en bruger rammer URL’en, til han/hun ser indholdet.
Her er en sammenligning. Jeg testede det på en udviklings-Mac.
React Rendered on Server
Den første interaktionstid er 300 ms. Hydrate afsluttes på 400 ms. Indlæsningshændelsen afsluttes på ca. 500 ms. Du kan se dette ved at se på billedet ovenfor.
React Rendered on Client’s Browser
Den første interaktionstid er 400ms. Indlæsningshændelsen afsluttes på 470 ms.
Resultatet taler for sig selv. Der er en forskel på 100 ms i den første brugerinteraktionstid for en så lille app.
Hvordan virker det? – (4 enkle trin)
- Opret en frisk Redux Store ved hver anmodning.
- Optionelt afsendes nogle handlinger.
- Hent tilstanden ud af Store og udfør SSR.
- Send den tilstand, der blev opnået i det foregående trin, sammen med svaret.
Vi vil bruge den tilstand, der er sendt i svaret, til at skabe den indledende tilstand på klientsiden.
Hvor du går i gang, skal du klone/downloade det komplette eksempel fra Github og bruge det som reference.
Kom i gang ved at opsætte vores app
Først skal du åbne din foretrukne editor og shell. Opret en ny mappe til din applikation. Lad os begynde.
npm init --yes
Fyld detaljerne ud. Når package.json
er oprettet, kopierer du nedenstående afhængigheder og scripts ind i den.
Installer alle afhængigheder ved at køre:
npm install
Du skal konfigurere Babel og webpack, for at vores build-script kan fungere.
Babel omdanner ESM og react til Node- og browserforstået kode.
Opret en ny fil .babelrc
, og sæt nedenstående linje ind i den.
{ "presets": }
webpack bundter vores app og dens afhængigheder i en enkelt fil. Opret en anden fil webpack.config.js
med følgende kode i den:
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: }}
Byggeprocessen udsender to filer:
-
assets/bundle.js
– ren klientsideapp. -
assets/client.js
– klientsidecompanion til SSR.
Mappen src/
indeholder kildekoden. De Babel-kompilerede filer placeres i views/
. views
-mappen oprettes automatisk, hvis den ikke er til stede.
Hvorfor skal vi kompilere kildefilerne?
Grunden er syntaksforskellen mellem ESM & CommonJS. Når vi skriver React og Redux, bruger vi i høj grad import og eksport i alle filer.
Der fungerer desværre ikke i Node. Her kommer Babel til undsætning. Scriptet nedenfor fortæller Babel at kompilere alle filer i mappen src
og lægge resultatet i views.
"babel": "babel src -d views",
Nu kan Node køre dem.
Kopiering af prækodede & statiske filer
Hvis du allerede har klonet repositoryet, skal du kopiere fra det. Ellers downloader du ssr-static.zip-filen fra Dropbox. Udpak den, og opbevar disse tre mapper i din app-mappe. Her er, hvad de indeholder.
- React
App
og komponenter befinder sig isrc/components
. - Redux-filer i
src/redux/
. -
assets/ & media/
: Indeholder statiske filer somstyle.css
og billeder.
Server Side
Opret to nye filer ved navn server.js
og template.js
inde i src/
-mappen.
src/server.js
Magien sker her. Dette er den kode, du har ledt efter.
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 };};
I stedet for at rendere vores app skal vi pakke den ind i en funktion og eksportere den. Funktionen accepterer applikationens oprindelige tilstand.
Sådan fungerer det.
- Passer
initialState
tilconfigureStore()
.configureStore()
tilbagegiver en ny Store-instans. Hold den inde istore
-variablen. - Kald
renderToString()
-metoden, og giv vores App som input. Den renderer vores app på serveren og returnerer den producerede HTML. Nu gemmer variablencontent
HTML’en. - Henter tilstanden ud af Redux Store ved at kalde
getState()
påstore
. Opbevar den i en variabelpreloadedState
. - Returnerer
content
ogpreloadedState
. Vi vil videregive disse til vores skabelon for at få den endelige HTML-side.
2. src/template.js
template.js
eksporterer en funktion. Den tager title
, state
og content
som input. Den injicerer dem i skabelonen og returnerer det endelige HTML-dokument.
For at videregive tilstanden vedhæfter skabelonen state
til window.__STATE__
inde i et <scri
pt>-tag.
Nu kan du læse state
på klientsiden ved at få adgang til window.__STATE__
.
Vi inkluderer også SSR-kammeraten assets/client.js
klientsideprogrammet i et andet scripttag.
Hvis du anmoder om den rene klientversion, lægger den kun assets/bundle.js
ind i scripttagget.
Klientsiden
Klientsiden er ret ligetil.
src/bundle.js
Det er sådan, du skriver React- og Redux-Provider
wrap’en. Det er vores rene klient-side-app. Ingen tricks her.
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
Ligner det bekendt? Ja, der er ikke noget særligt bortset fra window.__STATE__.
Det eneste, vi skal gøre, er at hente den indledende tilstand fra window.__STATE__
og sende den til vores configureStore()
-funktion som den indledende tilstand.
Lad os tage et kig på vores nye klientfil:
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'));
Lad os gennemgå ændringerne:
- Erstat
render()
medhydrate()
.hydrate()
er det samme somrender()
, men bruges til at hydrere elementer, der er gengivet afReactDOMServer
. Det sikrer, at indholdet er det samme på serveren og klienten. - Læs tilstanden fra det globale vinduesobjekt
window.__STATE__
. Gem den i en variabel, og sletwindow.__STATE__
. - Opret et nyt lager med
state
som initialState.
Alt er gjort her.
Sammensætning af det hele
Index.js
Det er indgangspunktet for vores program. Den håndterer anmodninger og templating.
Den deklarerer også en initialState
variabel. Jeg har modelleret den med data i assets/data.json
filen. Vi vil videregive den til vores ssr()
-funktion.
Bemærk: Når du henviser til en fil, der er inde i src/
, fra en fil uden for src/
, skal du bruge normal require()
og erstatte src/
med views/
. Du kender årsagen (Babel-kompilering).
Routing
-
/
: Som standard server-renderet hjemmeside. -
/client
: Eksempel på ren rendering på klientsiden. -
/exit
: Knap til serverstop. Kun tilgængelig i udvikling.
Build & Run
Det er tid til at bygge og køre vores program. Det kan vi gøre med en enkelt kodelinje.
npm run build && npm run start
Nu kører applikationen på http://localhost:3000.
Er du klar til at blive React Pro?
Jeg starter en ny serie fra næste mandag for at få dine React-færdigheder til at blusse op, med det samme.
Tak for at du læste dette.
Hvis du kan lide det og finder det nyttigt, så følg mig på Twitter & Webflow.