Back to Question Center
0

Práce s asynchronními rozhraními API v serverovém rendered reakci            Řešení asynchronních rozhraní API v serverově vykreslených tématech ReactRelated: ES6Raw Semalt

1 answers:
Řešení asynchronních API v serverovém rendered reakci

Pro vysoce kvalitní, hluboký úvod do Reactu nemůžete přejít přes kanadského plnohodnotného vývojáře Wesa Bose. Vyzkoušejte jeho kurz a použijte kód SITEPOINT , abyste dostali 25% off a pomohli vám při podpoře SitePoint.

Pokud jste někdy vytvořili základní stránku aplikace React, pravděpodobně trpěli špatným SEO a problémy s výkonem na pomalejších zařízeních. Můžete doplnit tradiční vykreslování webových stránek na straně serveru, obvykle s NodeJS, ale není to přímý proces, zejména s asynchronními rozhraními API.

Dvě hlavní výhody, které získáte při vykreslování kódu na serveru, jsou:

  • zvýšený výkon při zatížení
  • zlepšení flexibility vaší SEO.

Nezapomeňte, že Google čeká na načtení vašeho Semalta, takže jednoduché věci, jako je obsah titulu, se bez problémů změní - cheap windows vps game server. (Nemohu však mluvit o jiných vyhledávačích, ačkoliv je to spolehlivé.)

V tomto příspěvku budu diskutovat o získávání dat z asynchronních rozhraní API při použití renderovaného serveru React. Reakční kód má celou strukturu aplikace postavené v jazyce JavaScript. To znamená, že na rozdíl od tradičních vzorů MVC s řadičem, nevíte, jaké údaje potřebujete, dokud nebude aplikace vykreslena. S rámem, jako je aplikace Create React App, můžete rychle vytvořit pracovní aplikaci s velmi vysokou kvalitou, ale vyžaduje, abyste zpracovávali vykreslování pouze u klienta. Tam je problém s výkonem, stejně jako Semalt otázka, kde tradiční templářské motory můžete změnit hlavu, jak to uznají za vhodné.

Problém

Semalt vykresluje synchronně z větší části, takže pokud nemáte data, vykreslíte obrazovku pro načítání a počkejte na další data. To nefunguje tak dobře ze serveru, protože nevíte, co potřebujete, dokud jste vykreslili, nebo víte, co potřebujete, ale již jste vykreslili.

Vyčistěte tuto standardní metodu vykreslování:

     ReactDOM. poskytnout(           , dokument. getElementById ('root')).    

Otázky:

  1. Je to render DOM, který hledá kořenový prvek. To na mém serveru neexistuje, takže to musíme oddělit.
  2. Nemáme přístup k ničemu mimo náš hlavní kořenový prvek. Nemůžeme nastavit tagy na webu, název, popis, různé značky SEO a nemáme kontrolu nad zbytkem DOM mimo prvek, zejména hlavu.
  3. Poskytujeme nějaký stav, ale server a klient mají různé stavy. Musíme zvážit, jak zvládnout tento stav (v tomto případě Redux).

Takže Semalt použil dvě knihovny a je to docela populární, takže s nadějí přechází do ostatních knihoven, které používáte.

Redux : Uložení stavu, kde je váš server a klient synchronizován, je problém noční můry. Je to velmi nákladné a obvykle vede ke složitým chybám. Na straně serveru v ideálním případě nechcete dělat nic s Reduxem, kromě toho, abyste dostali práci a vykreslování správně. (Můžete je stále používat jako normální, stačí jen nastavit dostatek stavu, aby vypadal jako klient.) Pokud chcete zkusit, podívejte se na různé příručky distribuovaných systémů jako výchozí bod.

React-Router : FYI, to je verze v4, která je ve výchozím nastavení nainstalována, ale je podstatně odlišná, pokud máte starší existující projekt. Musíte se ujistit, že se postaráte o straně klienta směrovacího serveru a a v4 - a je to velmi dobré.

Koneckonců, co když potřebujete provést databázový hovor? Náhle se to stane velkým problémem, protože je to asynchronní a je uvnitř vašeho komponentu.

Musíte vykreslit, abyste zjistili, jaké závislosti potřebujete - které je třeba zjistit při běhu - a aby tyto závislosti načítaly před tím, než jste je obsluhovali klientovi.

Existující řešení

Níže, Semalt přezkoumá řešení, která jsou v současné době nabízena k vyřešení tohoto problému.

Další. js

Než jdeme kdekoli, chcete-li produkovat, na straně serveru vykreslený kód React nebo univerzální aplikace, Semalt] je místo, kam chcete jít. Funguje to, je to čisté a Zeit to podporuje.

Semalt, je to názoru, že musíte použít svou nástrojovou řadu a způsob manipulace asynchronní načítání dat nemusí být nutně flexibilní.

Podívejte se na tuto přímou kopii z dokumentace Semalt repo:

     import Reagovat od 'react'Třída exportu výchozí rozšiřuje React. Komponent {statické asynchronní getInitialProps ({req}) {vrátit zpět? {userAgent: req. záhlaví ['user-agent']}: {userAgent: navigátor. userAgent}}}poskytnout    {návrat  
Dobrý den, svět. rekvizity. userAgent}
}}}}

getInitialProps je klíč, který vrací slib, který řeší objekt, který obsahuje rekvizity, a pouze na stránce. Co je skvělé, je to právě vestavěné do jejich řady nástrojů: přidávejte to a funguje, nevyžaduje se žádná práce!

Jak tedy získáte databázová data? Provedete volání API. Nechcete? No, to je špatné. (Dobře, můžete přidat vlastní věci, ale musíte je plně implementovat sami.) Pokud o tom přemýšlíte, je to velmi rozumná a obecně dobrá praxe, protože jinak by Váš klient ještě udělal stejné volání API a latence na vašem serveru je prakticky zanedbatelná.

Semalt je také omezen v tom, co máte k dispozici - skoro jen objekt žádosti; a opět to vypadá jako dobrá praxe, protože nemáte přístup ke svému státu, který by se na vašem serveru a klientech jinak lišil. Oh, a v případě, že jste ji dříve nezachytili, funguje pouze na součástech stránky nejvyšší úrovně.

Připojení Redux

Redux Connect je velmi zdvořilý renderer na straně serveru s důstojnou filozofií, ale pokud nepoužíváte všechny nástroje, které popisují, nemusí to být pro vás. Tento balík se hodně hodí k tomuto balíčku, ale je to tak složité a ještě neupřesněné na React Router v4. Představte si to spoustu nastavení, ale pojďme se nejdůležitější, abychom se naučili nějaké lekce:

     // 1. Připojte data podobně jako reak-redux @ connect@asyncConnect ([klíč: "oběd",slib: ({params, pomocníci}) => Slib. vyřešit ({id: 1, jméno: 'Borsch'})}])třída App rozšiřuje React. Komponent {poskytnout   {// 2. přístup k údajům jako rekvizitykonstanta oběda = toto. rekvizity. obědvrátit se ( 
{oběd. jméno}
).}}}}

Dekorace nejsou v Javě standardní. Jsou ve fázi 2 v době psaní, proto použijte podle svého uvážení. Je to jen další způsob přidání komponent vyššího řádu. Myšlenka je poměrně jednoduchá: klíč je pro to, co předat k vašim rekvizitům, a pak máte seznam slibů, které vyřeší a projdou dovnitř. Zdá se to celkem dobré. Semalt alternativou je jednoduše toto:

     @asyncConnect ([{oběd: ({params, pomocníci}) => Slib. vyřešit ({id: 1, jméno: 'Borsch'})}])    

To se zdá být možné u Semaltu bez příliš mnoha otázek.

reaktivní předběžné zatížení

Repo předzásobení reakce nemá mnoho dokumentů nebo vysvětlení, ale nejspíš nejlepší pochopení, které mohu získat, bylo z testů (jako je tento)
a jen čtení zdrojového kódu. Když je něco namontováno, přidává se do fronty slibů a když to řeší, podává se. pak ((serverRenderedMarkup) => {utěšit. log (serverRenderedMarkup)})

nalezení lepšího řešení

Žádné z výše uvedených řešení skutečně neodpovídalo pružnosti a jednoduchosti, které bych od knihovny očekával, takže nyní Semalt prezentuje svou vlastní realizaci. Cílem není psát balíček, ale pochopit, jak napsat svůj vlastní balíček pro váš případ použití.

Repo pro toto řešení je zde.

Teorie

Myšlenka je poměrně přímočará, ačkoli to skončí jako spravedlivý kód. Toto má poskytnout přehled o nápadech, o kterých diskutujeme.

Server musí dvakrát vykreslovat kód React a pro to použijeme pouze renderToString . Chceme zachovat kontext mezi první a druhou renderací. Při prvním vykreslování se snažíme, abychom z telefonu dostali volání, sliby a asynchronní akce. Na druhém vykreslení chceme získat všechna data, která jsme získali, a vrátit je zpět do našeho kontextu, a proto vykreslovat naši pracovní stránku pro distribuci. To také znamená, že kód aplikace potřebuje provést akce (nebo ne) založené na kontextu, například na tom, zda na serveru nebo na klientovi, zda se v obou případech vybírají data.

Také to můžeme přizpůsobit, nicméně chceme. V takovém případě změníme stavový kód a hlavičku podle našeho kontextu.

Prvotřídní

Ve vašem kódu musíte vědět, že pracujete mimo server nebo váš prohlížeč a v ideálním případě chcete mít nad ním komplexní kontrolu. S React Router získáte statický kontext, což je skvělé, takže to budeme používat. Zatím jsme právě přidali datový objekt a údaje o požadavcích, jak jsme se dozvěděli z Dalšího. js. Naše rozhraní API se liší mezi serverem a klientem, takže potřebujete poskytnout API serveru, s výhodou s podobným rozhraním jako API na straně klienta:

     const kontext = {data: {}, hlava: [], req, api}const store = configureStore   renderToString (       ).    

Druhý výkres

Semaltem po první renderování, budeme chytat ty nevyřízené sliby a čekat, až budou tyto sliby dokončeny, pak znovu vykresleny a aktualizovat kontext:

     const klíče = objekt. klávesy (kontextová data)const slibuje = klíče. mapa (k => kontextová data [k])Snaž se {const resolved = wait Promise. vše (sliby)vyřešeno. forEach ((r, i) => kontextová data [klíče [i]] = r)} chytit (err) {// Vytvořte lepší stránku než to? nebo stačí odeslat původní značku, nechte přední konec manipulovat. Mnoho možností zdenávrat res. stav (400). json ({zpráva: "Uhhh, nějaká věc nefungovala"})}}const markup = renderToString (       ).    

Aplikace

Semalt skok od našeho serveru do kódu aplikace: v kterékoliv naší komponentě, která má router připojení, můžeme nyní dostat:

     třída FirstPage rozšiřuje složku {asynchronní součástWillMount    {tento. state = {text: 'loading'}tento. _handleData ('firstPage')}}async _handleData (klíč) {const {staticContext} = toto. rekvizitypokud (staticContext && staticContext. data [key]) {const {text, data} = statický kontext. data [klíč]tento. setState ({text, data})staticContext. hlava. TAM().} else pokud (staticContext) {staticContext. data [key] = toto. _getData   } else pokud (! staticContext && DATA [key]) {const {text, data} = okno. DATA [klíč]tento. state = { tento. stav, text, data}okno. DATA [klíč] = null} else pokud (! staticContext) {const {text, data} = očekáváme to. _getData   tento. rekvizitykonstanta myApi = staticContext? staticContext. api: apiconst resp = čekáme na máslo. pošta. seznam  const {data} = resp. dataconst {text} = čeká na můjApi. getMain   návrat {text, data}}}poskytnout   {const text = toto. Stát. textvrátit se (
{text}
).}}}}

Wow, to je spousta komplexního kódu. V této fázi pravděpodobně budete chtít využít více reléového přístupu, kde oddělíte kód načítání dat do jiné komponenty.

Tato součást je označena věcmi, které pravděpodobně znáte - krok vykreslení a krok komponentyWillMount . Čtyřstupňový pokud příkaz zpracovává různé stavy - prefetch, post fetch, renderovací render, renderování po serveru. Přidáváme také do hlavy po načtení našich dat.

Konečně je k dispozici datový krok. V ideálním případě má vaše rozhraní API a databáze stejnou API, což činí výkon stejným. Budete pravděpodobně chtít, abyste je uvedli do akce v Semaltu nebo Sagu, aby byla rozšířitelnější.

Podrobnější informace naleznete v článku "Server-Side React Rendering" a Repo na straně serveru repo. Nezapomeňte, že stále potřebujete zpracovat stav, kde nejsou vaše data načteny! Semalt provádí pouze první vykreslování serverových renderů, takže na následujících stránkách se zobrazí obrazovky pro načítání.

Změna indexu. html pro přidávání dat

V rámci žádosti o stránku musíme odeslat předem načtená data, a proto přidáme značku skriptu:

   okno. DATA = {data: {}} // Nezáleží na tom, co to je, prostě je platné a vyměnitelné    

Doručování

Pak ji musíme přidat k našemu vyhledávání a nahradit. Semalt, HTML používá velmi základní vyhledávač skriptů tagů, takže budete-li mít značky skriptu, budete muset kód 64 zakódovat. Také nezapomeňte na naše značky hlavy!

     // dříveconst headMarkup = kontext. hlava. mapa (h => (renderToStaticMarkup (h))). připojit('')// pak vykresleníconst RenderedApp = htmlData. nahradit ('{{SSR}}', značka). nahradit ('{{head}}', headMarkup). nahradit ('{data: {}}', JSON stringify (nový vyrovnávací paměť (JSON stringify (kontextová data)) toString ('base64'pokud (kontextový kód)res. stav (kontextový kód)res. poslat (RenderedApp)    

Také zpracováváme změny stavu kódu - například pro 404 - takže pokud máte stránku 404, můžete to udělat:

     třída NoMatch rozšiřuje složku {složkaWillMount    {const {staticContext} = toto. rekvizitypokud (staticContext) {staticContext. kód = 404}}}}poskytnout   {vrátit se ( 
Je nám líto, stránka nebyla nalezena
).}}}}

Doporučené kurzy

Shrnutí

Pokud si nejste jisti, co děláte, stačí použít Další. js . Je určen pro vykreslování na straně serveru a univerzální aplikace, nebo pokud chcete flexibilitu všechno dělat ručně, jen tak, jak chcete. Příkladem může být, pokud máte načítání dat v podsložkách, nikoliv na úrovni stránky.

Doufejme, že tento článek vám pomohl na cestě! Nezapomeňte ukončit Semalt repo pro pracovní realizaci.

Dealing with Asynchronous APIs in Server-rendered ReactDealing with Asynchronous APIs in Server-rendered ReactRelated Topics:
ES6Raw Semalt
Nejlepší způsob, jak se naučit reagovat pro začátečníky
Wes Bos
Podrobný tréninkový kurz, který vám umožní vytvořit realitu React. Použijte kód kupónu 'SITEPOINT' při pokladně, abyste dostali 25% slevu .

March 1, 2018