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 React szerveren történő renderelésének hátrányai
- Mikor érdemes használni a szerveroldali megjelenítést?
- SEO
- Teljesítmény javítása
- React Rendered on Server
- React Rendered on Client’s Browser
- Hogyan működik? – (4 egyszerű lépés)
- Kezdés az alkalmazásunk beállításával
- Miért kell lefordítani a forrásfájlokat?
- Másolja az előkódolt & statikus fájlokat
- Server Side
- src/server.js
- 2. src/template.js
- A kliensoldal
- src/bundle.js
- src/client.js
- Az egészet összerakjuk
- Index.js
- Build & Run
- Készen állsz arra, hogy React Pro legyél?
- Köszönöm, hogy elolvastad ezt.
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:
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
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
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:
-
assets/bundle.js
– tiszta kliens oldali alkalmazás. -
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.
- React
App
és a komponensek asrc/components
. - Redux fájlok a
src/redux/
. -
assets/ & media/
mappában találhatóak: Statikus fájlokat tartalmaz, példáulstyle.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.
- Pass
initialState
aconfigureStore()
-be.configureStore()
visszaad egy új Store példányt. Tartsuk astore
változóban. - 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 acontent
változó tárolja a HTML-t. - Hozzuk ki az állapotot a Redux Store-ból a
getState()
hívásával astore
-on. Tartsuk meg apreloadedState
változóban. - Visszaadjuk vissza a
content
és apreloadedState
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 <scri
pt> 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:
- Cseréljük ki a
render()
-et ahydrate()
-re. Ahydrate()
ugyanaz, mint arender()
, de aReactDOMServer
által renderelt elemek hidratálására szolgál. Ez biztosítja, hogy a tartalom azonos legyen a kiszolgálón és a kliensen. - A globális ablakobjektum
window.__STATE__
állapotának beolvasása. Tároljuk egy változóban, és töröljük awindow.__STATE__
-ot. - 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
-
/
: Alapértelmezés szerint szerver által renderelt honlap. -
/client
: Tisztán kliensoldali renderelési példa. -
/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.
Köszönöm, hogy elolvastad ezt.
Ha tetszik és hasznosnak találod, kövess engem a Twitteren & Webflow.