A legjobb mindkét világból: SSR izomorf JavaScript

szerver oldali renderelés, vagy SSR, egy olyan kifejezés, amelyet gyakran hall a frontend fejlesztői közösségben.

a legalapvetőbb szinten a szerveroldali renderelés pontosan az, amit leír: alkalmazások renderelése a szerveren. Navigálsz egy weboldalra, az kérést küld a szervernek, renderel egy kis HTML-t, és a teljes renderelt eredményt visszaadod a böngésződbe. Elég egyértelmű. Lehet, hogy felteszi magának a kérdést, hogy a közösségnek miért is van erre szlogenje.

a gazdag és dinamikus webes alkalmazások megjelenése előtt, amelyek nagymértékben támaszkodtak a JavaScript-re és a jQuery-re, lényegében minden webes alkalmazás szerver-renderelt volt. A PHP, a WordPress, sőt csak az alapvető HTML oldalak is példák erre.

amikor meglátogat egy oldalt ezen oldalak egyikén, visszakapja az összes HTML — adatot és mindent. Ha rákattint egy linkre, a böngésző újabb kérést küld a szervernek. A válasz után a böngésző frissíti és megjeleníti a következő oldalt az alapoktól kezdve. Ez a megközelítés jól működik, és évek óta; a böngészők látványosan gyors renderelés statikus HTML. Mi változott?

mivel a századforduló, JavaScript használat ment egy kis szórja itt-ott a weboldal interaktivitás a vitathatatlan nyelv a választás az interneten. Folyamatosan több logikát és Javascriptet szállítunk a böngészőbe.

az olyan egyoldalas keretrendszerek, mint a React és a Vue, megnyitották a dinamikus, összetett, adatvezérelt kliens-renderelt webes alkalmazások új korszakát. Ezek a gyógyfürdők abban különböznek a szerver által renderelt alkalmazásoktól, hogy a képernyőn történő megjelenítés előtt nem töltenek le teljesen renderelt tartalmat a szerver adataival együtt.

az ügyféloldali renderelt alkalmazások JavaScript használatával jelenítik meg tartalmukat a böngészőben. Ahelyett, hogy az összes tartalmat lekérnék a szerverről, egyszerűen lekérnek egy barebone HTML oldalt, amelynek nincs törzstartalma,és az összes tartalmat JavaScript segítségével renderelik.

ennek az az előnye, hogy elkerüli a teljes oldal frissítéseit, amelyek a teljesen szerver által megjelenített alkalmazásoknál történnek, ami kissé zavaró lehet a felhasználó számára. Az egyoldalas, ügyfél által megjelenített alkalmazások frissítik a képernyőn megjelenő tartalmat, adatokat gyűjtenek az API-kból, és közvetlenül az Ön előtt frissítik, bármilyen oldalfrissítés nélkül. Ez a jellemző az, ami a modern webes alkalmazásokat szellemesnek és “natívnak” érzi, amikor kapcsolatba lép velük.

ügyféloldali renderelési kompromisszumok

ez nem minden napsütés és szivárvány a kliens oldali renderelt SPA világban. Vannak kompromisszumok, amelyek az alkalmazás ügyféloldali megjelenítésével járnak. Két fő példa a SEO és a kezdeti terhelési teljesítmény.

SEO

mivel az ügyfél által megjelenített alkalmazások egy csupasz HTML-oldalt adnak vissza, amely nagyon kevés tartalommal rendelkezik, mielőtt a JavaScript beindul, és a többit rendereli, a keresőmotorok számára nehéz lehet megérteni az oldal HTML-szerkezetét, ami káros a webhely keresési rangsorolására. A Google sok jó munkát végzett ezzel kapcsolatban, de továbbra is ajánlott elkerülni az ügyféloldali megjelenítést, ha a SEO különösen fontos.

kezdeti terhelési teljesítmény

az ügyfél által megjelenített alkalmazások esetében általában a következő dolgok történnek az oldal első megnyitásakor:

  • az alkalmazás betölti néhány alapvető HTML, mint egy alkalmazás shell vagy statikus navbar
  • látsz egy betöltési mutatója valamilyen
  • A tartalom akkor renderelt

a probléma ezzel az, hogy az alkalmazás nem mutat semmit, amíg a JavaScript betölti teljesen a hálózatról, és kész rendering elemeket rá a képernyőn.

dióhéjban az ügyféloldali teljesítmény problémája általában az, hogy nem tudja ellenőrizni, hogy valaki milyen kliens eszközön használja az alkalmazást-legyen az a legkorszerűbb okostelefon, a nagy teljesítményű csúcskategóriás asztali gép vagy a 100 dolláros alsó kategóriás okostelefon.

mi azonban vezéreljük a szervert. Szinte mindig több CPU-t és memóriát adhatunk a szerverünknek, és módosíthatjuk, hogy jobban teljesítsen a felhasználóink számára.

mindkét világ legjobbjai

mindkét világ legjobbjai lehetnek, ha szerveroldali renderelést használunk modern frontend technológiákkal. Ez általában úgy működik, hogy a szerver az első betöltéskor rendereli és visszaküldi a teljesen renderelt alkalmazást. A következő lépés, az úgynevezett hidratálás, ahol a JavaScript csomag letöltésre és végrehajtásra kerül. Ez csatolja eseménykezelők és vezetékek dolgokat, mint a kliens oldali router.

ezzel a megközelítéssel megkapja az SSR összes előnyét a kezdeti terhelésnél, majd minden interakciót ettől a ponttól kezdve a kliens oldali JavaScript kezeli. Ez gyors, SEO-barát kezdeti terhelést biztosít, amelyet a dinamikus egyoldalas webes alkalmazás-élmény követ, amelyet ismerünk és szeretünk.

az ilyen alkalmazásokat univerzális alkalmazásoknak nevezzük, mivel ugyanaz a JavaScript fut a kliensen és a kiszolgálón. Hallhatja az “izomorf” kedvelő kifejezést is, ami pontosan ugyanazt jelenti.

oktatóanyag: az SSR végrehajtása

az SSR sem mentes a kompromisszumoktól. Növeli a fejlesztést azáltal, hogy összetettebb konfigurációt vezet be, valamint saját szervert kell üzemeltetnie és kezelnie. Ezek a problémák miért hihetetlen keretek, mint a következő.a js és a Razzle nagyon népszerűek: elvonják az SSR konfigurációs részét, és lehetővé teszik, hogy az UI kód írására összpontosítson.

ebben az oktatóanyagban nem fogunk SSR keretrendszereket használni. A legjobb módja annak, hogy megtanulják, hogyan működik valami valójában az épület, így fogunk tanulni, hogyan lehet létrehozni a legegyszerűbb SSR beállítás tudjuk esetleg, hogy biztosítani fogja:

  • globális CDN
  • teljesen működőképes backend API
  • nincs szerver vagy infrastruktúra a
  • Egyparancsos telepítés

egy univerzális szerver által nyújtott React alkalmazást fogunk telepíteni a create-react-app segítségével az Amazon Web Services (AWS) szolgáltatásban. Nem kell, hogy van tapasztalata AWS követni végig.

eszközeink

alkalmazásunk felépítéséhez néhány különböző AWS szolgáltatást fogunk igénybe venni.

  • AWS felerősítése: Magas szintű keretrendszer az AWS szolgáltatások kezeléséhez, főleg mobil és webfejlesztéshez
  • AWS Lambda: kód futtatása a felhőben szerverek kezelése nélkül
  • AWS Cloudfront (CDN): tartalomszolgáltató hálózat, amely felelős a tartalom kézbesítéséért és gyorsítótárazásáért az egész világon
  • AWS Simple Storage Service (S3): ahol statikus eszközeinket (JS, CSS, stb.) tároljuk.)

architektúra diagram

Lambda funkciónk felelős a React alkalmazás szerver-megjelenítéséért. Az S3-at statikus tartalom tárolására, a Cloudfront CDN-t pedig annak kiszolgálására fogjuk használni. Nem kell előzetes ismeretekkel rendelkeznie ezekről a szolgáltatásokról, mivel az AWS Amplify rendkívül egyszerűvé teszi számunkra azok létrehozását.

 építészeti Diagramunk

építészeti Diagramunk

alkalmazásunk felépítése

először telepítenie kell az AWS Amplify CLI-t, és létre kell hoznia egy AWS-fiókot, ha még nincs. Ezt a rövid útmutatót követve teheti meg.

projektbeállítás

most, hogy az Amplify konfigurálva van, elkezdhetjük a React projekt beállítását. A fantasztikus create-react-alkalmazást fogjuk használni, hogy segítsen nekünk. Feltételezve, hogy van csomópont.JS és npm telepítve, tudjuk futtatni:

npx create-react-app amplify-ssrcd amplify-ssr yarn add aws-amplify amplify init

válassza ki az alapértelmezett beállításokat az AWS erősítő varázslóban.

a React projektünk most az Amplify-val van feltöltve, és készen áll arra, hogy hozzáadjuk a “szerverünket” az SSR-hez. Ezt a amplify add api futtatásával és néhány kérdés megválaszolásával végezzük:

$ amplify add api? Please select from one of the below mentioned services: REST? Provide a friendly name for your resource to be used as a label for this category in the project: amplifyssr? Provide a path (e.g., /items): /ssr? Choose a Lambda source: Create a new Lambda function? Provide a friendly name for your resource to be used as a label for this category in the project: amplifyssr? Provide the AWS Lambda function name: ssr? Choose the function runtime that you want to use: NodeJS? Choose the function template that you want to use: Serverless expressJS function? Do you want to access other resources created in this project from your Lambda function? N? Do you want to edit the local lambda function now? N? Restrict API access: N? Do you want to add another path? N

ez létrehozza a megfelelő sablonokat, könyvtárakat és kódokat, amelyek szükségesek az AWS infrastruktúránkhoz és háttérrendszerünkhöz: egy AWS Lambda függvény, amely egy kis Express szervert fog futtatni, amely felelős a React alkalmazásunk megjelenítéséért.

mielőtt telepítenénk az infrastruktúrát, néhány változtatásra van szükségünk a React alkalmazásunkban, hogy felkészítsük a szerveroldali megjelenítésre. Nyissa meg a src/App.js (a React alkalmazás fő alkalmazásösszetevője) elemet, majd illessze be a következőbe:

import React from 'react';function App() { return ( <div className="App"> <header className="App-header"> Server Rendered React App </header> </div> );}export default App;

ezután létre kell hoznunk egy szkriptet, amely a React alkalmazást a szerver oldalon jeleníti meg. Ez a renderToString funkcióval történik a react-dom/server csomagban. Ez a funkció felelős azért, hogy a <App /> komponenst a szerver oldalon karakterláncként rendereljük, készen arra, hogy teljesen renderelt HTML-ként visszaküldjük a kliensnek.

hozzon létre egy fájlt src/render.js címen a következő kóddal:

import React from "react";import { renderToString } from "react-dom/server";import App from "./App";export default () => renderToString(<App />);

nagyszerű-az ügyféloldali React alkalmazásunk rendelkezik az összes kóddal, amelyet a szerver oldalon kell megjeleníteni. Ez azt jelenti, hogy most be kell kódolnunk a szerver oldali végpontot, amely a React alkalmazásunkat teszi lehetővé.

van egy probléma, bár — szükségünk van a src/render függvény és a <App /> komponens kódot kell futtatni a szerver oldalon. A szerver alapértelmezés szerint semmit sem tud a React vagy akár az ES modulokról. Ezért a kódot a Babel segítségével a React alkalmazásból a szerver oldalra fogjuk átültetni.

ehhez telepítsünk néhány Babel függőséget a projektünkbe.

yarn add --dev @babel/core @babel/cli @babel/preset-react @babel/preset-env

ezután hozzon létre egy .babelrc értéket a projekt gyökerében. Ez a fájl a Babel konfigurálására szolgál, és megmondja, hogy mely bővítményeket/preseteket használja.

{ "presets":}

végül frissítsük a package.json – et, hogy a kódot a build lépés részeként fordítsuk át. Ez transzpilálja a fájlokat a amplify/backend/function/amplifyssr/src/client könyvtárba, ahol tároljuk az összes univerzális Javascriptet, amelyet a kliens oldalon kell futtatni, valamint az SSR szerverét.

 "scripts": { "start": "react-scripts start", "transpile": "babel src --out-dir amplify/backend/function/amplifyssr/src/client --copy-files", "build": "npm run transpile && react-scripts build && npm run copy", "copy": "cp build/index.html amplify/backend/function/amplifyssr/src/client", "test": "react-scripts test", "eject": "react-scripts eject" },

teszi az alkalmazást Lambda

a build konfiguráció befejeződött! Ugorjunk a amplify/backend/function/amplifyssr/src – ba, és telepítsük a react – et és a react-dom – et, mivel mindkettőre szükség lesz a Lambda SSR végrehajtásához.

yarn add react react-dom

most konfiguráljuk az Express szervert, amely Lambda-n fog futni. A Lambda függvény automatikusan generálódott számunkra, amikor korábban elvégeztük a amplify add api lépést, és egy REST és ExpressJS API-t választottunk.

az Amplify már konfigurálta az Express szervert, hogy Lambda-n fusson, így csak annyit kell tennünk, hogy hozzáadunk egy végpontot a szerverhez-rendereljük a React alkalmazást, amikor valaki eléri az API URL-t a böngészőben. Frissítse a amplify/backend/function/amplifyssr/src/app.js fájlt a következő kódra:

/* Amplify Params - DO NOT EDIT ENV REGIONAmplify Params - DO NOT EDIT */const express = require('express')const bodyParser = require('body-parser')const awsServerlessExpressMiddleware = require('aws-serverless-express/middleware')const fs = require('fs');const render = require('./client/render').default;// declare a new express appconst app = express()app.use(bodyParser.json())app.use(awsServerlessExpressMiddleware.eventContext())// Enable CORS for all methodsapp.use(function(req, res, next) { res.header("Access-Control-Allow-Origin", "*") res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept") next()});app.get('*', function(req, res) { // Read the index.html file from the create-react-app build const html = fs.readFileSync("./client/index.html", "utf-8"); // Server side render the react application const markup = render(); // Replace the empty body of index.html with the fully server rendered react application and send it back to the client res.send(html.replace(`<div></div>`, `<div>${markup}</div>`))});module.exports = app

az Express szerverünk SSR-kész, és telepíthetjük React alkalmazásunkat.

tárhely és utolsó simítások

miután megkaptuk a szerver által renderelt HTML vissza a mi app kezdeti render, akkor majd letölteni a kliens oldali JavaScript csomagot, hogy vegye át onnan, és ad nekünk egy teljesen interaktív SPA.

kell egy hely, ahol a kliens oldali JavaScript-et és statikus fájlokat tárolhatjuk. Az AWS-ben az ehhez általában használt szolgáltatás az S3 (Simple Storage Service), egy masszívan skálázható felhőobjektum-tároló.

egy CDN-t is teszünk elé a globális gyorsítótár és teljesítmény érdekében. Az Amplify segítségével mindkét erőforrást létrehozhatjuk a projektünkhöz, ha néhány parancsot futtatunk a projekt gyökérkönyvtárából:

$ amplify add hostingSelect the plugin module to execute Amazon CloudFront and S3? Select the environment setup: PROD (S3 with CloudFront using HTTPS)? hosting bucket name (name your bucket or use the default)

a teljes infrastruktúrát, beleértve az Express server Lambda függvényt, Az S3 bucket-et és a CDN-t, a amplify publish parancs futtatásával telepítheti.

a konzol kimenete megmutatja az Amplify által létrehozott sablonok összes releváns erőforrását. Felhívjuk figyelmét, hogy a Cloudfront CDN létrehozása eltarthat egy ideig, ezért legyen türelmes. Az erőforrások létrehozása után a Cloudfront CDN URL megjelenik a terminálon.

Publish started for S3AndCloudFront✔ Uploaded files successfully.Your app is published successfully.https://d3gdcgc9a6lz30.cloudfront.net

az utolsó dolog, amit meg kell tennünk, hogy megmondjuk a React-nek, honnan kell letölteni az ügyféloldali csomagot, miután az alkalmazást a szerver renderelte. Ez a create-react-app alkalmazásban történik a PUBLIC_URL környezeti változó használatával. Frissítsük újra a React app package.json szkriptjeinket, hogy a következők legyenek:

 "scripts": { "start": "react-scripts start", "transpile": "babel src --out-dir amplify/backend/function/amplifyssr/src/client --copy-files", "build": "npm run transpile && PUBLIC_URL=<your-cloudfront-url> react-scripts build && npm run copy", "copy": "cp build/index.html amplify/backend/function/amplifyssr/src/client", "test": "react-scripts test", "eject": "react-scripts eject" },

ezzel a frissített konfigurációval építse újra és telepítse az alkalmazást az AWS-re.

amplify publish

most már egy teljesen szerveroldali renderelt React app fut AWS!

fut a app

az SSR API URL megtalálható amplify/backend/amplify-meta.json. Keresse meg a RootUrl fájlt a JSON fájlban, és látnia kell azt az URL-t, amelyen meglátogathatja az új szerver által megjelenített alkalmazást. Úgy kell kinéznie, mint a következő:

"output": { "ApiName": "amplifyssr", "RootUrl": "https://g6nfj3bvsg.execute-api.eu-west-1.amazonaws.com/dev", "ApiId": "g6nfj3bvsg"}, 

keresse fel böngészőjében az API Gateway URL-jét a <your-api-url>/ssr címen, és látnia kell a fényes új szerver által nyújtott React alkalmazást! Ha belemerül a választott böngésző hálózat lapjába, és megnézi a kéréseket, észre fogja venni, hogy a /ssr – hoz intézett kérésnek teljesen renderelt HTML-válasza van, a React alkalmazásunk pedig a dokumentum <body> – ben jelenik meg.

<div> <div class="App" data-reactroot=""> <header class="App-header">Server Rendered React App</header> </div></div>

azt is észre a kéréseket, hogy a Cloudfront URL a böngésző betölteni a kliens oldali JavaScript, amely átveszi rendering innen, így nekünk a legjobb mind a kliens oldali és szerver oldali rendering világok.

Hová menjünk innen

ennek az oktatóanyagnak az a célja, hogy a lehető leggyorsabban elindítsa és futtassa a kiszolgálóoldali renderelést anélkül, hogy aggódnia kellene az infrastruktúra, a CDN-ek stb. Miután használta a szerver nélküli megközelítés, van néhány szép fejlesztések tudjuk, hogy a Beállítás.

kiépített konkurencia

az egyik módja annak, hogy az AWS Lambda rendkívül alacsony költségű maradjon, az, hogy a Lambda funkciók, amelyeket egy ideje nem találtak el, “tétlen” lesz.”Ez lényegében azt jelenti, hogy amikor újra végrehajtjuk őket, lesz egy úgynevezett “hidegindítás” — egy inicializálási késleltetés, amelynek meg kell történnie, mielőtt a Lambda reagál.

ezt követően a lambda egy ideig ismét “meleg”, és gyorsan reagál a későbbi kérésekre a következő hosszú üresjárati időszakig. Ez kissé megbízhatatlan válaszidőket okozhat.

annak ellenére, hogy “kiszolgáló nélküli”, a Lambda könnyű tárolókat használ a kérelmek feldolgozásához. Minden konténer egyszerre csak egy kérést képes feldolgozni. A tétlen időszak utáni hidegindítási probléma mellett ugyanez igaz akkor is, ha sok egyidejű kérés ugyanazt a Lambda függvényt érinti, ami több egyidejű konténer vagy munkavállaló hidegindítását okozza, mielőtt válaszolna.

a múltban sok mérnök megoldotta ezt a problémát azáltal, hogy szkripteket írt a Lambda rendszeres pingelésére, hogy melegen tartsa. Most már van egy sokkal jobb AWS-natív módszer ennek megoldására, amelyet Provisioned Concurrency néven ismerünk.

a kiépített konkurencia, akkor nagyon könnyen kérheti egy adott számú dedikált konténerek melegen tartani egy adott Lambda funkciót. Ez sokkal következetesebb SSR válaszidőt biztosít a magas és szórványos terhelés idején.

Lambda verziók

több Lambda verziót hozhat létre a funkcióihoz, és megoszthatja a forgalmat közöttük. Ez nagyon erős az SSR alkalmazásunkban, mivel lehetővé teszi számunkra, hogy frissítéseket hajtsunk végre a Lambda oldalon, és a/B teszteljük őket a felhasználók kisebb részével.

a Lambda több verzióját is közzéteheti, és a forgalmat a megadott súlyokban oszthatja meg. Előfordulhat például, hogy kiszolgálón renderel egy CTA szalaghirdetést egyes felhasználók számára az elkötelezettség mérésére, mások számára azonban nem. Ezt a Lambda verziókkal teheti meg.

Full-stack webalkalmazás

amint azt korábban kifejtettük, az AWS Amplify már létrehoz egy REST API-t és egy Express szervert számunkra, amelyben létrehoztunk egy végpontot a React alkalmazás szerver-rendereléséhez. Mindig több kódot és végpontot adhatunk ehhez az Express szerverhez a amplify/backend/function/amplifyssr/src/app.js címen, lehetővé téve számunkra, hogy alkalmazásunkat teljes verem webes alkalmazássá alakítsuk, adatbázissal, hitelesítéssel és még sok mással kiegészítve.

használhatja az AWS Amplify eszközök fantasztikus csomagját ezen erőforrások létrehozásához vagy a saját infrastruktúrájához való csatlakoztatáshoz — még akkor is, ha nem az AWS-en található. Az AWS Lambda backendjét úgy kezelheti, mint bármely más Express szervert,és építhet rá.

a teljes telepítési folyamatot már beállította a amplify publish futtatásával, így a kód írására összpontosíthat. Ennek az oktatóanyagnak a kiindulópontja teljes rugalmasságot biztosít ahhoz, hogy innen megtehesse, amit akar.

következtetés

a szerveroldali megjelenítésnek nem kell nehéznek lennie. Használhatunk olyan teljesen felügyelt eszközöket, mint a Next vagy a Razzle, amelyek önmagukban csodálatosak, de sok csapat számára ez túl nagy paradigmaváltás lehet, tekintettel a meglévő kódjukra vagy követelményeikre. Egy egyszerű, alacsony karbantartási igényű, egyedi megközelítés megkönnyítheti az életet, különösen, ha már használja az AWS-t vagy az Amplify-t a projektjéhez.

az SSR rengeteg értéket adhat a webes alkalmazásokhoz, és nagyon szükséges teljesítményt vagy SEO lendületet adhat. Szerencsések vagyunk a webfejlesztő közösségben, hogy olyan eszközökkel rendelkezünk, amelyek CDN-eket, kiszolgáló nélküli backendeket és teljesen hosztolt webes alkalmazásokat hozhatnak létre néhány parancs vagy kattintás segítségével.

még ha nem is gondolod, hogy szükséged van SSR-re, ez egy nagyon elterjedt és gyakori téma a JavaScript ökoszisztémában. Az előnyök és a kompromisszumok megértése hasznos lesz szinte bárki számára, aki részt vesz a webfejlesztési szférában.

remélem, ma tanultál valamit — köszönöm az olvasást! Nyugodtan lépjen kapcsolatba velem, vagy kövessen a Twitteren, ahol tweetelek és blogolok a Javascriptről, Pythonról, AWS-ről, automatizálásról és kód nélküli fejlesztésről.

teljes láthatóság a production React alkalmazásokban

a React alkalmazások hibakeresése nehéz lehet, különösen akkor, ha a felhasználók nehezen reprodukálható problémákat tapasztalnak. Ha érdekel a Redux állapot figyelése és nyomon követése, a JavaScript hibák automatikus felszínre kerülése, valamint a lassú hálózati kérések és az összetevők betöltési ideje, próbálja meg a LogRocket alkalmazást. LogRocket Dashboard Free Trial Banner

A LogRocket olyan, mint egy DVR a webes alkalmazásokhoz, szó szerint mindent rögzít, ami a React alkalmazásban történik. Ahelyett, hogy kitalálná, miért fordulnak elő problémák, összesítheti és jelentést tehet arról, hogy az alkalmazás milyen állapotban volt, amikor egy probléma történt. A LogRocket az alkalmazás teljesítményét is figyeli, olyan mutatókkal számol be, mint az ügyfél CPU-terhelése, az ügyfél memóriahasználata stb.

a LogRocket Redux köztes szoftvercsomag egy extra láthatósági réteget ad a felhasználói munkamenetekhez. A LogRocket naplózza az összes műveletet és állapotot a Redux áruházakból.

modernizálja a React alkalmazások hibakeresésének módját — kezdje el a felügyeletet ingyen.

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

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