Hogyan valósítsuk meg a szerveroldali renderelést a React alkalmazásunkban három egyszerű lépésben

By Rohit Kumar

Ez az, amit ebben a bemutatóban építeni fogunk: egy ilyen szép React kártyát.

A bemutatóban a szerveroldali renderelést fogjuk használni, hogy HTML választ adjunk, amikor egy felhasználó vagy lánctalpas elér egy oldal URL címét. Az utóbbi kéréseket kliensoldalon fogjuk kezelni.

Miért van erre szükségünk?

Hadd vezessem el a válaszhoz.

Mi a különbség a kliensoldali renderelés és a szerveroldali renderelés között?

A kliensoldali renderelés során a böngésző letölt egy minimális HTML-oldalt. Rendereli a JavaScriptet, és kitölti a tartalmat.

A szerveroldali renderelés ezzel szemben a React komponenseket a szerveren rendereli. A kimenet a HTML tartalom.

Ezt a kettőt kombinálva izomorf alkalmazást hozhat létre.

A React szerveren történő renderelésének hátrányai

  • AzSSR javíthatja a teljesítményt, ha az alkalmazás kicsi. De ronthatja is a teljesítményt, ha nehéz.
  • Növeli a válaszidőt (és rosszabb lehet, ha a szerver elfoglalt).
  • Növeli a válaszméretet, ami azt jelenti, hogy az oldal betöltése tovább tart.
  • Növeli az alkalmazás összetettségét.

Mikor érdemes használni a szerveroldali megjelenítést?

Az SSR ezen következményei ellenére vannak olyan helyzetek, amikor lehet és kell használni.

SEO

Minden weboldal szeretne megjelenni a keresésekben. Javítson ki, ha tévedek.

Sajnos a keresőmotorok lánctalpasai még nem értik/megjelenítik a JavaScriptet.

Ez azt jelenti, hogy egy üres oldalt látnak, függetlenül attól, hogy mennyire hasznos a webhelyed.

Sokan mondják, hogy a Google lánctalpasai már megjelenítik a JavaScriptet.

A teszteléshez az alkalmazást Herokun telepítettem. Íme, amit a Google Search Console-ban láttam:

A Google lánctalpasítója nem rendereli a Reactot

Egy üres oldal.

Ez volt a legnagyobb ok, amiért felfedeztem a szerveroldali renderelést. Különösen akkor, ha ez egy olyan sarkalatos oldal, mint egy landing page, blog stb.

Hogy ellenőrizze, hogy a Google rendereli-e az oldalát, látogasson el:

Search Console Dashboard > Crawl > Fetch as Google. Adja meg az oldal URL-címét, vagy hagyja üresen a kezdőlap esetében.

Válassza a FETCH AND RENDER lehetőséget. Ha elkészült, kattintson az eredmény megtekintéséhez.

Teljesítmény javítása

Az SSR-ben az alkalmazás teljesítménye a kiszolgáló erőforrásaitól és a felhasználó hálózati sebességétől függ. Ez nagyon hasznos a tartalomigényes webhelyek esetében.

Tegyük fel például, hogy van egy közepes árú mobiltelefonja, lassú internetsebességgel. Megpróbál hozzáférni egy olyan webhelyhez, amely 4 MB adatot tölt le, mielőtt bármit is láthatna.

Sikerülne 2-4 másodpercen belül bármit is látni a képernyőn?

Meglátogatná újra azt a webhelyet?

Nem hiszem, hogy meglátogatná.

Egy másik jelentős javulás az első felhasználói interakciós idő. Ez az az időkülönbség, amely a felhasználónak az URL elérésétől a tartalom megjelenéséig tart.

Itt az összehasonlítás. Egy fejlesztői Mac-en teszteltem.

React Rendered on Server

SSR teljesítményjelentés (Chrome)

Az első interakciós idő 300 ms. A hidrát 400 ms alatt fejeződik be. A betöltési esemény körülbelül 500ms után lép ki. Ezt a fenti képen láthatja.

React Rendered on Client’s Browser

Kliensoldali teljesítményjelentés (Chrome)

Az első interakciós idő 400ms. A betöltési esemény 470 ms után lép ki.

Az eredmény magáért beszél. 100ms különbség van az első felhasználói interakciós időben egy ilyen kis alkalmazás esetében.

Hogyan működik? – (4 egyszerű lépés)

  • Létrehoz egy friss Redux Store-t minden egyes kérésnél.
  • Opticionálisan elküld néhány műveletet.
  • Hozd ki az állapotot a Store-ból és végezd el az SSR-t.
  • Az előző lépésben kapott állapotot küldd el a válasszal együtt.

A válaszban átadott állapotot fogjuk használni a kliensoldali kezdeti állapot létrehozásához.

Mielőtt belekezdünk, klónozzuk/letöltsük le a teljes példát a Githubról és használjuk referenciaként.

Kezdés az alkalmazásunk beállításával

Először is nyissuk meg a kedvenc szerkesztőnket és shellünket. Hozzunk létre egy új mappát az alkalmazásunknak. Kezdjük el.

npm init --yes

Töltsük ki a részleteket. A package.json létrehozása után másoljuk bele az alábbi függőségeket és szkripteket.

Installáljuk az összes függőséget a következő futtatással:

npm install

A Babel és a webpack konfigurálására van szükségünk ahhoz, hogy a build szkriptünk működjön.

A Babel az ESM-et és a react-ot Node és böngésző által érthető kóddá alakítja át.

Készítsünk egy új .babelrc fájlt, és tegyük bele az alábbi sort.

{ "presets": }

A webpack egyetlen fájlba csomagolja az alkalmazásunkat és annak függőségeit. Hozzunk létre egy másik webpack.config.js fájlt a következő kóddal:

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: }}

A build folyamat kimenete két fájl:

  1. assets/bundle.js – tiszta kliens oldali alkalmazás.
  2. assets/client.js – kliens oldali társ az SSR-hez.

A src/ mappa tartalmazza a forráskódot. A Babel lefordított fájljai a views/ mappába kerülnek. A views könyvtár automatikusan létrejön, ha nincs meg.

Miért kell lefordítani a forrásfájlokat?

Az ok az ESM & CommonJS közötti szintaxisbeli különbség. A React és Redux írása során minden fájlban erősen használjuk az import és export funkciókat.

Ezek sajnos nem működnek a Node-ban. Itt jön a Babel, hogy megmentse. Az alábbi szkript utasítja a Babelt, hogy fordítsa le az összes fájlt a src könyvtárban, és tegye az eredményt a views.

"babel": "babel src -d views",

Most, a Node tudja futtatni őket.

Másolja az előkódolt & statikus fájlokat

Ha már klónozta a repository-t, másolja le róla. Ellenkező esetben töltse le az ssr-static.zip fájlt a Dropboxból. Csomagolja ki, és tartsa ezt a három mappát az alkalmazás könyvtárában. Íme, mit tartalmaznak.

  1. React App és a komponensek a src/components.
  2. Redux fájlok a src/redux/.
  3. assets/ & media/ mappában találhatóak: Statikus fájlokat tartalmaz, például style.css és képeket.

Server Side

Létrehoz két új fájlt server.js és template.js néven a src/ mappában.

src/server.js

A varázslat itt történik. Ez az a kód, amit kerestél.

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 };};

Ahelyett, hogy renderelnénk az alkalmazásunkat, be kell csomagolnunk egy függvénybe és exportálnunk kell. A függvény elfogadja az alkalmazás kezdeti állapotát.

Íme, így működik.

  1. Pass initialState a configureStore()-be. configureStore()visszaad egy új Store példányt. Tartsuk a store változóban.
  2. Hívjuk meg a renderToString() metódust, bemenetként megadva az alkalmazásunkat. Ez rendereli az alkalmazásunkat a szerveren, és visszaadja az előállított HTML-t. Most a content változó tárolja a HTML-t.
  3. Hozzuk ki az állapotot a Redux Store-ból a getState() hívásával a store-on. Tartsuk meg a preloadedState változóban.
  4. Visszaadjuk vissza a content és a preloadedState változót. Ezeket átadjuk a sablonunknak, hogy megkapjuk a végleges HTML oldalt.

2. src/template.js

template.js exportál egy függvényt. Ez title, state és content értékeket fogad el bemenetként. Ezeket befecskendezi a sablonba, és visszaadja a végleges HTML-dokumentumot.

Az állapot átadásához a sablon a window.__STATE__-hoz csatolja a state-ot egy <script> címkén belül.

Az window.__STATE__-hoz való hozzáféréssel most már a kliensoldalon is olvasható a state.

A kliensoldali SSR-társ assets/client.js alkalmazást is egy másik script-tagbe foglaljuk.

Ha a tiszta kliensverziót kérjük, akkor csak assets/bundle.js kerül a script tagbe.

A kliensoldal

A kliensoldal elég egyszerű.

src/bundle.js

Így írjuk meg a React és Redux Provider wrap-et. Ez a mi tiszta kliensoldali alkalmazásunk. Itt nincsenek trükkök.

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

Ismerősnek tűnik? Igen, nincs semmi különös, kivéve window.__STATE__. Mindössze annyit kell tennünk, hogy elkapjuk a kezdeti állapotot a window.__STATE__-ból és átadjuk a configureStore() függvényünknek kezdeti állapotként.

Vessünk egy pillantást az új kliens fájlunkra:

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'));

Nézzük át a változásokat:

  1. Cseréljük ki a render()-et a hydrate()-re. A hydrate() ugyanaz, mint a render(), de a ReactDOMServer által renderelt elemek hidratálására szolgál. Ez biztosítja, hogy a tartalom azonos legyen a kiszolgálón és a kliensen.
  2. A globális ablakobjektum window.__STATE__ állapotának beolvasása. Tároljuk egy változóban, és töröljük a window.__STATE__-ot.
  3. Készítsünk egy új tárolót state mint initialState.

Minden itt készült el.

Az egészet összerakjuk

Index.js

Ez az alkalmazásunk belépési pontja. Ez kezeli a kéréseket és a templatingot.

Ez egy initialState változót is deklarál. Ezt a assets/data.json fájlban lévő adatokkal modelleztem. Ezt fogjuk átadni a ssr() függvényünknek.

Megjegyzés: Amikor egy src/-en belüli fájlra hivatkozunk egy src/-en kívüli fájlból, használjuk a normál require()-ot, és a src/ helyett views/-t használjuk. Tudod az okát (Babel compile).

Routing

  1. /: Alapértelmezés szerint szerver által renderelt honlap.
  2. /client: Tisztán kliensoldali renderelési példa.
  3. /exit: Szerver leállítás gomb. Csak fejlesztésben elérhető.

Build & Run

Eljött az idő, hogy elkészítsük és futtassuk az alkalmazásunkat. Ezt egyetlen kódsorral megtehetjük.

npm run build && npm run start

Most, az alkalmazás fut http://localhost:3000.

Készen állsz arra, hogy React Pro legyél?

Jövő hétfőtől új sorozatot indítok, hogy a React készségeid azonnal lángra lobbanjanak.

előfizetési link alább ?

Köszönöm, hogy elolvastad ezt.

Ha tetszik és hasznosnak találod, kövess engem a Twitteren & Webflow.

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.