To nejlepší z obou světů: SSR s isomorfním JavaScriptem

Vykreslování na straně serveru, nebo SSR, je fráze, kterou často slyšíte ve vývojové komunitě frontend.

na nejzákladnější úrovni je Vykreslování na straně serveru přesně to, co popisuje: Vykreslování aplikací na serveru. Přejdete na web, odešle požadavek na server, vykreslí nějaký HTML a dostanete plně vykreslený výsledek zpět do prohlížeče. Docela přímočaré. Možná se ptáte sami sebe, proč má komunita pro to dokonce módní slovo.

před vzestupem bohatých a dynamických webových aplikací, které se silně spoléhaly na JavaScript a jQuery, byly v podstatě všechny webové aplikace vykresleny serverem. Příkladem jsou PHP, WordPress a dokonce i základní HTML stránky.

když navštívíte stránku na jednom z těchto webů, dostanete zpět všechna data HTML a všechny. Pokud kliknete na odkaz, prohlížeč podá další požadavek na server. Po odpovědi prohlížeč obnoví a vykreslí další stránku od základů. Tento přístup funguje dobře, a to má po celá léta; prohlížeče jsou úžasně rychlé při vykreslování statického HTML. Co se změnilo?

od přelomu století se používání JavaScriptu změnilo z malého posypání sem a tam pro interaktivitu webových stránek na nesporný jazyk volby na webu. Neustále dodáváme do prohlížeče více logiky a JavaScriptu.

jednostránkové rámce jako React a Vue zavedly tuto novou éru dynamických, komplexních, datově řízených klientských webových aplikací. Tyto lázně se liší od aplikací vykreslených na serveru, protože nenačtou plně vykreslený obsah doplněný daty ze serveru před vykreslením na obrazovce.

aplikace na straně klienta vykreslují svůj obsah v prohlížeči pomocí JavaScriptu. Spíše než načítání veškerého obsahu ze serveru, jednoduše načtou stránku barebones HTML bez obsahu těla a vykreslí veškerý obsah uvnitř pomocí JavaScriptu.

výhodou je, že se vyhnete úplnému obnovení stránky, ke kterému dochází u plně serverově vykreslených aplikací, což může být pro uživatele trochu nepříjemné. Jednostránkové aplikace vykreslené klientem aktualizují obsah na obrazovce, načtou data z rozhraní API a aktualizují přímo před vámi bez jakéhokoli obnovení stránky. Tato vlastnost je to, co dělá moderní webové aplikace cítit pohotový a „nativní“, jak budete komunikovat s nimi.

klient-side rendering kompromisy

to není všechno slunce a duhy v klient-side-tavené SPA světě. Existují některé kompromisy, které přicházejí s vykreslením vaší aplikace na straně klienta. Dva primární příklady jsou SEO a počáteční výkon zatížení.

SEO

vzhledem k tomu, že aplikace poskytnuté klientem vracejí stránku HTML s holými kostmi s velmi malým obsahem, než JavaScript začne a vykreslí zbytek, může být pro prohledávače vyhledávačů obtížné pochopit strukturu HTML vaší stránky, což je škodlivé pro hodnocení vyhledávání vašeho webu. Google udělal hodně dobré práce kolem toho, ale stále se doporučuje vyhnout se Vykreslování na straně klienta, pokud je SEO obzvláště důležité.

počáteční výkon načítání

u aplikací vykreslených klientem se při prvním otevření stránky obvykle vyskytují následující věci:

  • aplikace načte některé základní HTML, jako app shell nebo statické navbar
  • vidíte indikátor načítání nějakého druhu
  • váš obsah je pak vykreslen

problém s tím je, že vaše aplikace nebude zobrazovat nic, dokud JavaScript načte úplně ze sítě a je dokončena vykreslování prvků na obrazovce.

Stručně řečeno, problém s výkonem na straně klienta obecně spočívá v tom, že nemůžete ovládat, na jakém klientském zařízení někdo používá vaši aplikaci – ať už je to jejich nejmodernější smartphone — výkonný špičkový stolní počítač nebo smartphone nižší úrovně $ 100.

server však ovládáme. Téměř vždy můžeme dát našemu serveru více CPU a paměti a vyladit jej tak, aby byl pro naše uživatele lepší.

to nejlepší z obou světů

při použití serverového Vykreslování s moderními frontendovými technologiemi můžeme mít to nejlepší z obou světů. Způsob, jakým to obecně funguje, je, že server vykreslí a odešle zpět plně vykreslenou aplikaci při prvním načtení. Dalším krokem, známý jako hydratace, je místo, kde bude stažen a spuštěn váš JavaScript bundle. To připojí manipulátory událostí a zapojí věci jako směrovač na straně klienta.

s tímto přístupem získáte všechny výhody SSR při počátečním zatížení, pak každá interakce od tohoto bodu dopředu bude zpracována JavaScriptem na straně klienta. To zajišťuje rychlé, SEO-přátelské počáteční zatížení, následované dynamickým jednostránkovým zážitkem z webové aplikace, který známe a milujeme.

takové aplikace jsou známé jako univerzální aplikace, protože stejný JavaScript běží na klientovi a serveru. Můžete také slyšet milovník termín „izomorfní“ se používá, což znamená přesně to samé.

Tutorial: implementace SSR

SSR není bez kompromisů. To přidává režii do svého vývoje zavedením složitější konfiguraci, stejně jako museli hostit a spravovat svůj vlastní server. Tyto problémy jsou důvodem neuvěřitelných rámců jako Next.js a Razzle jsou velmi populární: abstrahují konfigurační část SSR a umožňují vám soustředit se na psaní kódu uživatelského rozhraní.

v tomto tutoriálu nebudeme používat žádné rámce SSR. Nejlepší způsob, jak se naučit, jak něco funguje, je skutečně jej postavit, takže se naučíme, jak vytvořit nejjednodušší nastavení SSR, které můžeme poskytnout:

  • Globální CDN
  • plně funkční backend API
  • žádné servery nebo infrastruktura pro správu
  • nasazení jednoho příkazu

chystáme se nasadit univerzální serverovou aplikaci React vytvořenou pomocí create-react-app na Amazon Web Services (AWS). Nemusíte mít zkušenosti s AWS, abyste mohli následovat.

naše nástroje

abychom mohli vytvořit naši aplikaci, využijeme několik různých služeb AWS.

  • AWS Amplify: Rámec na vysoké úrovni pro správu služeb AWS, zejména pro vývoj mobilních a webových aplikací
  • AWS Lambda: spusťte kód v cloudu bez správy serverů
  • AWS Cloudfront (CDN): síť pro doručování obsahu odpovědná za doručování a ukládání do mezipaměti po celém světě
  • AWS Simple Storage Service (S3): kde uložíme naše statická aktiva (JS, CSS atd.)

schéma architektury

naše Lambda funkce je zodpovědná za serverové Vykreslování naší aplikace React. Budeme používat S3 k ukládání našeho statického obsahu a Cloudfront CDN k jeho servírování. Nemusíte mít žádné předchozí znalosti o těchto službách, protože AWS Amplify nám usnadní jejich vytváření.

naše schéma architektury

náš diagram architektury

budování naší aplikace

nejprve je třeba nainstalovat AWS Amplify CLI a vytvořit účet AWS, pokud jej již nemáte. Můžete tak učinit podle tohoto krátkého průvodce.

Nastavení projektu

Nyní, když je Amplify nakonfigurován, můžeme začít nastavovat náš projekt React. Použijeme fantastickou aplikaci create-react, která nám pomůže. Za předpokladu, že máte uzel.JS a npm nainstalován, můžeme spustit:

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

Vyberte výchozí možnosti v průvodci zesílením AWS.

náš projekt React je nyní bootstrapped s Amplify a připraven pro nás přidat náš „server“ pro SSR. Děláme to spuštěním amplify add api a zodpovězením některých otázek:

$ 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

tím se vytvoří příslušné šablony, adresáře a kód potřebný pro naši infrastrukturu AWS a backend: funkce AWS Lambda, která bude provozovat malý Expresní server zodpovědný za Vykreslování naší aplikace React.

než nasadíme naši infrastrukturu, musíme provést některé změny v naší aplikaci React, abychom ji připravili pro vykreslování na straně serveru. Otevřete src/App.js (hlavní součást aplikace pro vaši aplikaci React) a vložte následující:

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

dále musíme vytvořit skript, který vykreslí naši aplikaci React na straně serveru. To se provádí pomocí funkce renderToString v balíčku react-dom/server. Tato funkce je zodpovědná za převzetí naší komponenty <App /> a její vykreslení na straně serveru jako řetězec, připravený k vrácení jako plně vykreslený HTML klientovi.

Vytvořte soubor na src/render.js s následujícím kódem:

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

skvělé – náš klient-side React aplikace má veškerý kód, který potřebuje být vykreslen na straně serveru. To znamená, že nyní musíme kódovat koncový bod na straně serveru, který vykreslí naši aplikaci React.

máme však problém – potřebujeme funkci src/render a náš kód komponenty <App /> spustit na straně serveru. Server ve výchozím nastavení neví nic o modulech React nebo dokonce ES. Z tohoto důvodu se chystáme transpilovat kód z aplikace React pomocí Babel na stranu serveru.

Chcete-li to provést, nainstalujte do našeho projektu několik závislostí Babel.

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

dále vytvořte .babelrc v kořenovém adresáři projektu. Tento soubor slouží ke konfiguraci Babel a říct mu, které pluginy / předvolby použít.

{ "presets":}

nakonec aktualizujme náš package.json, abychom transpilovali náš kód jako součást kroku sestavení. Tím se transpilují soubory do adresáře amplify/backend/function/amplifyssr/src/client, kde uložíme veškerý univerzální JavaScript, který je třeba spustit na straně klienta, stejně jako server pro SSR.

 "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" },

vykreslení aplikace v Lambda

konfigurace sestavení je dokončena! Pojďme skočit do amplify/backend/function/amplifyssr/src a nainstalovat react a react-dom, protože oba budou vyžadovány pro Lambda k provedení SSR.

yarn add react react-dom

nyní nakonfigurujte náš Expresní server, který bude spuštěn na Lambda. Funkce Lambda byla pro nás automaticky generována, když jsme dokončili krok amplify add api dříve a zvolili API REST a ExpressJS.

Amplify již nakonfiguroval Expresní server, abychom mohli běžet na Lambda, takže vše, co nyní musíme udělat, je přidat koncový bod na server-vykreslete naši aplikaci React, když někdo zasáhne URL API v prohlížeči. Aktualizujte soubor amplify/backend/function/amplifyssr/src/app.js tak, aby obsahoval následující kód:

/* 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

náš Expresní server je nyní připraven na SSR a můžeme nasadit naši aplikaci React.

Hosting a poslední úpravy

Jakmile obdržíme HTML vykreslený serverem zpět z počátečního vykreslení naší aplikace, načteme balíček JavaScriptu na straně klienta, který odtud převezme a poskytne nám plně interaktivní lázně.

potřebujeme někde hostit JavaScript a statické soubory na straně klienta. V AWS je služba obecně používaná pro tento účel S3 (Simple Storage Service), masivně škálovatelné úložiště cloudových objektů.

také před něj umístíme CDN pro globální ukládání do mezipaměti a výkon. S Amplify, můžeme vytvořit oba tyto zdroje pro náš projekt spuštěním několika příkazů z kořenového adresáře projektu:

$ 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)

nyní můžete nasadit celou infrastrukturu, včetně funkce Express server Lambda, kbelíku S3 a CDN, spuštěním příkazu amplify publish.

výstup konzoly zobrazí všechny relevantní zdroje z vašich šablon vytvořených pro vás pomocí Amplify. Vezměte prosím na vědomí, že vytvoření Cloudfront CDN může chvíli trvat, takže buďte trpěliví. Po vytvoření zdrojů se v terminálu zobrazí adresa URL vašeho CDN Cloudfront.

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

poslední věc, kterou musíme udělat, je říct React, odkud načíst náš balíček na straně klienta poté, co je aplikace vykreslena serverem. To se provádí v create-react-app pomocí proměnné prostředí PUBLIC_URL. Pojďme aktualizovat naše React app package.json skripty znovu vypadat takto:

 "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" },

obnovte a nasaďte svou aplikaci do AWS s touto aktualizovanou konfigurací.

amplify publish

nyní bychom měli mít na AWS plně vykreslenou aplikaci React na straně serveru!

spuštění naší aplikace

vaše SSR API URL lze nalézt na amplify/backend/amplify-meta.json. Vyhledejte RootUrl v souboru JSON a měli byste vidět adresu URL, na které můžete navštívit novou aplikaci vykreslenou serverem. Mělo by vypadat něco jako následující:

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

navštivte adresu URL brány API ve Vašem prohlížeči na adrese <your-api-url>/ssr a měli byste vidět svou novou lesklou aplikaci React vykreslenou serverem! Pokud se ponoříte do karty síť ve Vašem prohlížeči a zobrazíte požadavky, všimnete si, že požadavek na /ssr má plně vykreslenou odpověď HTML s naší aplikací React vykreslenou uvnitř <body> dokumentu.

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

také si všimnete požadavků na adresu URL Cloudfront z prohlížeče, abyste načetli JavaScript na straně klienta, který odtud převezme Vykreslování, což nám dává to nejlepší z obou světů Vykreslování na straně klienta i na straně serveru.

kam jít odtud

tento tutoriál je určen k tomu, aby vás co nejrychleji spustil a spustil Vykreslování na straně serveru bez obav o správu infrastruktury, CDN a dalších. Po použití přístupu bez serveru existuje několik pěkných vylepšení, které můžeme provést v našem nastavení.

poskytnutá souběžnost

jedním ze způsobů, jak může AWS Lambda zůstat extrémně nízkonákladová, je to, že funkce Lambda, které nebyly za chvíli zasaženy, půjdou “ nečinně.“To v podstatě znamená, že když je znovu provedeme, bude to, co se nazývá „studený start“ – Inicializační zpoždění, ke kterému musí dojít dříve, než Lambda odpoví.

poté je lambda po určitou dobu opět „teplá“ a bude rychle reagovat na následné požadavky až do dalšího dlouhého období nečinnosti. To může způsobit mírně nespolehlivé doby odezvy.

přestože je Lambda „bez serveru“, používá ke zpracování všech požadavků lehké kontejnery. Každý kontejner může zpracovat pouze jeden požadavek v daném okamžiku. Kromě problému se studeným startem po nečinnosti platí totéž, když mnoho souběžných požadavků zasáhne stejnou funkci Lambda, což způsobí, že více souběžných kontejnerů nebo pracovníků bude před odpovědí spuštěno za studena.

v minulosti mnoho inženýrů vyřešilo tento problém psaním skriptů, které pravidelně ping Lambda udržují v teple. Nyní existuje mnohem lepší způsob, jak to vyřešit pomocí AWS-native, a je známý jako Zajištěná souběžnost.

s poskytnutou souběžností můžete velmi snadno požádat o určitý počet vyhrazených kontejnerů, aby zůstaly teplé pro konkrétní funkci Lambda. To vám poskytne mnohem konzistentnější dobu odezvy SSR v době vysokého a sporadického zatížení.

verze Lambda

pro své funkce můžete vytvořit několik verzí Lambda a rozdělit provoz mezi nimi. To je v naší aplikaci SSR velmi silné, protože nám umožňuje provádět aktualizace na straně Lambda a A/B je testovat s menší částí uživatelů.

můžete publikovat několik verzí vašeho Lambda a rozdělit provoz mezi nimi ve váhách, které určíte. Například, možná budete chtít server-vykreslit CTA banner pro některé uživatele k měření zapojení, ale ne vykreslit to pro ostatní. Můžete to udělat s verzemi Lambda.

Full-stack webová aplikace

jak bylo vysvětleno dříve, AWS Amplify již pro nás vytváří REST API a expresní server, ve kterém jsme vytvořili koncový bod pro server-render naši aplikaci React. Na tento Expresní server můžeme vždy přidat další kód a koncové body na amplify/backend/function/amplifyssr/src/app.js, což nám umožňuje proměnit naši aplikaci v webovou aplikaci s plným zásobníkem, kompletní s databází, autentizací a dalšími.

můžete využít fantastickou sadu nástrojů AWS Amplify k vytvoření těchto zdrojů nebo k připojení do vlastní infrastruktury-i když není hostována na AWS. S backendem AWS Lambda můžete zacházet jako s jakýmkoli jiným expresním serverem a stavět na něm.

máte již celý svůj plán nasazení nastaven spuštěním amplify publish, takže se můžete soustředit na psaní kódu. Výchozí bod v tomto tutoriálu vám dává úplnou flexibilitu dělat to, co chcete odtud.

závěr

Vykreslování na straně serveru nemusí být těžké. Můžeme použít plně spravované nástroje jako Next nebo Razzle, které jsou samy o sobě úžasné, ale pro mnoho týmů to může být příliš velký posun paradigmatu vzhledem k jejich stávajícímu kódu nebo požadavkům. Použití jednoduchého, nenáročného na údržbu, vlastní přístup může usnadnit život, zejména pokud již pro svůj projekt používáte AWS nebo Amplify.

SSR může přidat spoustu hodnoty do vašich webových aplikací a poskytnout tolik potřebný výkon nebo SEO podporu. V komunitě pro vývoj webových aplikací máme štěstí, že máme nástroje, které mohou vytvářet CDN, backendy bez serverů a plně hostované webové aplikace s několika příkazy nebo kliknutími.

i když si nemyslíte, že potřebujete SSR, je to velmi rozšířené a běžné téma v ekosystému JavaScript. Pochopení jeho výhod a kompromisů se hodí téměř každému, kdo se podílí na sféře vývoje webu.

doufám, že jste se dnes něco naučili-díky za čtení! Neváhejte mě kontaktovat nebo mě sledujte na Twitteru, kde pípám a bloguji o JavaScriptu, Python, AWS, automatizace, a vývoj bez kódu.

Plná viditelnost do produkčních aplikací React

ladění aplikací React může být obtížné, zvláště když uživatelé mají problémy, které je obtížné reprodukovat. Pokud máte zájem o sledování a sledování stavu Redux, automatické vynořování chyb JavaScriptu a sledování pomalých požadavků na síť a doby načítání komponent, zkuste LogRocket. LogRocket Dashboard zdarma zkušební Banner

LogRocket je jako DVR pro webové aplikace, záznam doslova vše, co se děje na vaší aplikaci React. Místo hádání, proč k problémům dochází, můžete agregovat a podat zprávu o tom, v jakém stavu byla vaše aplikace, když došlo k problému. LogRocket také sleduje výkon vaší aplikace, hlášení s metrikami, jako je zatížení klienta CPU, využití paměti klienta a další.

balíček LogRocket Redux middleware přidává další vrstvu viditelnosti do Vašich uživatelských relací. LogRocket zaznamenává všechny akce a stav z vašich obchodů Redux.

modernizujte způsob ladění aplikací React – začněte sledovat zdarma.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.