renderToPipeableStream
API’si
renderToPipeableStream
— bu React 18’da joriy qilingan server tomonidagi rendering API’si bo’lib, katta hajmdagi React ilovalarini samaraliroq va moslashuvchanroq tarzda Node.js oqimiga o’tkazish imkonini beradi. Bu “stream” qaytaradi va uni javob (response) obyektiga uzatish mumkin. renderToPipeableStream
HTML qanday render qilinishini yaxshiroq boshqarish va boshqa Node.js oqimlari bilan yaxshiroq integratsiyani ta’minlash imkonini beradi.
Bundan tashqari, u React’ning “concurrent” xususiyatlarini, jumladan, Suspense’ni to’liq qo’llab-quvvatlaydi, bu esa server tomonidagi renderlash davomida asinxron ma’lumotlarni olishni yaxshiroq boshqarish imkonini ochib beradi. Stream bo’lganligi sababli, u tarmoq orqali uzluksiz uzatish holatida bo’lishi mumkin, ya’ni HTML qismlari bloklanmagan holda asinxron va yig’ilib boruvchi tarzda tarmoq orqali klientlarga yuboriladi. Bu tezkorroq TTFB (birinchi baytga erishish vaqti) va umuman yaxshiroq ishlash samaradorligi ko’rsatkichlarini ta’minlaydi.
Oldingi server kodimizni renderToPipeableStream
yordamida qayta yozish uchun quyidagicha o’zgartirish qilamiz:
const express = require("express");
const path = require("path");
const React = require("react");
const ReactDOMServer = require("react-dom/server");
const App = require("./src/App");
const app = express();
app.use(express.static(path.join(__dirname, "build")));
app.get("*", (req, res) => {
// O'zgarishlar shu yerda boshlanadi
const { pipe } = ReactDOMServer.renderToPipeableStream(<App />, {
// Ilova o'z ma'lumotlarini olishdan oldin tayyor bo'lsa
onShellReady: () => {
// Klientga HTML yuborilishini bildiramiz
res.setHeader("Content-Type", "text/html");
pipe(res); // React oqimini chiqishini javob oqimiga uzatish
},
});
});
app.listen(3000, () => {
console.log("Server 3000-portda ishlamoqda");
});
Keling, renderToPipeableStream
ni chuqurroq o’rganamiz, uning xususiyatlari, afzalliklari va qo’llanilish holatlari haqida muhokama qilamiz. Shuningdek, ushbu API’ni React ilovalaringizda qanday amalga oshirishni yaxshiroq tushunishingizga yordam berish uchun bir qancha kod namunalari va misollarni taqdim etamiz.
Bu qanday ishlaydi
renderToPipeableStream
ham renderToString
funksiyasiga o’xshab, deklarativ tarzda tasvirlangan React elementlari daraxtini oladi va uni HTML satriga aylantirish o’rniga, Node.js oqimi(stream)ga aylantiradi. Node.js stream — bu Node.js ishchi muhiti(runtime environment) asosidagi fundamental tushuncha bo’lib, samarali tarzda ma’lumotlarni qayta ishlash va boshqarishni ta’minlaydi. Oqimlar ma’lumotlarni bir maromda, bo’laklarga bo’lib ishlash imkoniyatini beradi, bu esa barcha ma’lumotlar to’plamini bir vaqtning o’zida xotiraga yuklamasdan amalga oshiriladi. Bu yondashuv katta satrlar yoki xotiraga sig’maydigan yoki tarmoq orqali uzatilishi mumkin bo’lmagan ma’lumotlar oqimlari bilan ishlashda ayniqsa foydali bo’ladi.
Node.js oqimlari (Node.js streams)
Asosan, Node.js oqimi manba va manzil o’rtasida uzluksiz uzatilayotgan ma’lumotlar oqimini ifodalaydi. Bu ma’lumotlar oqadigan truboprovod kabi tasavvur qilinishi mumkin, yo’lda turli xil operatsiyalar qo’llaniladi va ma’lumotlar qayta ishlanadi.
Node.js oqimlari tabiati va ma’lumotlar oqimi yo’nalishiga qarab to’rtta turga bo’linadi:
- O’qiladigan oqimlar (Readable streams): O’qiladigan oqimlar ma’lumotlar manbasini ifodalaydi, undan ma’lumot o’qishingiz mumkin. U
data
,end
vaerror
kabi event’larni tarqatadi. O’qiladigan oqimlarga fayldan ma’lumot o’qish, HTTP so’rovini qabul qilish yoki maxsus generator yordamida ma’lumot yaratish misollar kiradi. React’ningrenderToPipeableStream
funksiyasi HTML oqimini o’qishingiz va uni Express’dagires
javob obyektiga o’xshash yoziladigan oqimga chiqarishingiz mumkin bo’lgan o’qiladigan oqimni qaytaradi. - Yoziladigan oqimlar (Writable streams): Yoziladigan oqimlar ma’lumotlar yozilishi mumkin bo’lgan manzilni ifodalaydi. U
write()
vaend()
kabi metodlar orqali oqimga ma’lumot yuborish imkonini beradi. Agar manzil ko’proq ma’lumotlarni qabul qila oladigan bo’lsa, yoziladigan oqimlardrain
event’ini, yozish paytida xatolik yuz berganida esaerror
event’ini tarqatadi. Yoziladigan oqimlarning misoli sifatida Express’dagires
javob obyektini keltirish mumkin. - Ikki tomonlama oqimlar (Duplex streams): Dupleks(ikki tomonlama) oqimlar ham o’qiladigan, ham yoziladigan oqimni bir vaqtning o’zida ifodalaydi. Bu ikki tomonlama ma’lumotlar oqimini ta’minlaydi, ya’ni oqimdan o’qish va unga yozish imkonini beradi. Dupleks oqimlar odatda tarmoq soketlari yoki ma’lumotlar ikki yo’nalishda oqishi kerak bo’lgan aloqa kanallari uchun qo’llaniladi.
- Transform oqimlar (Transform streams): Transform oqimlar — bu ma’lumotlar oqimi orqali o’tayotganda ularni qayta ishlaydigan dupleks oqimning maxsus turi. U kiruvchi ma’lumotlarni o’qiydi, ularni qayta ishlaydi va qayta ishlangan ma’lumotlarni chiquvchi natija sifatida taqdim etadi. Transform oqimlar siqish, shifrlash, siqilgan ma’lumotlarni yechish yoki ma’lumotlarni tahlil qilish kabi vazifalarni bajarish uchun ishlatilishi mumkin.
Node.js oqimlarining kuchli xususiyatlaridan biri oqimlar orasida ma’lumotni ulash (piping qilish) imkoniyatidir. Piping usuli o’qiladigan oqimning chiqishini yoziladigan oqimning kirishiga ulashga imkon beradi va bu ma’lumotlar oqimini uzluksiz amalga oshirishni ta’minlaydi. Bu usul ma’lumotlarni boshqarish jarayonini ancha soddalashtiradi va xotira sarfini kamaytiradi. Haqiqatan ham, React’da server tomonida oqim orqali ishlov berish shunday amalga oshiriladi.
Node.js oqimlari ortiqcha bosim(backpressure)ni boshqarishni ham qo’llab-quvvatlaydi. Ortiqcha bosim — bu ma’lumotlarni qayta ishlash vaqtida yuz beradigan muammo bo’lib, u ma’lumotlar bufer ortida yig’ilib qolishini ifodalaydi. Yoziladigan oqim yetarlicha tez ma’lumotlarni qayta ishlay olmaganda, o’qiladigan oqim data
event’larini tarqatishni to’xtatadi va bu ma’lumotlar yo’qotilishining oldini oladi. Yoziladigan oqim ko’proq ma’lumotlarni qabul qilishga tayyor bo’lganida, drain
event’ini chiqaradi va o’qiladigan oqim data
event’larini tarqatishni davom ettiradi.
Ko’p chuqurlashmasdan va mavzudan chetlashmagan holda aytganda, Node.js oqimlari katta hajmdagi ma’lumotlar to’plamlarini, faylga kirish/chiqish operatsiyalarini, tarmoq aloqalarini samarali tarzda boshqarish va xotira tejamkor usulda amalga oshirish uchun kuchli abstraksiya hisoblanadi.
renderToPipeableStream
qanday ishlaydi
React’da komponentlarni yoziladigan oqimga aylantirishning maqsadi server tomonidan qayta ishlangan ilovalarning birinchi baytning kelishi vaqti (TTFB) samaradorligini oshirishdir. HTML markup’ini to’liq yaratilib, klientga yuborilishini kutish o’rniga, ushbu usullar serverga tayyor bo’lgan har bir bo’lak HTML javobini ketma-ket yuborishni boshlashga imkon beradi va shu bilan umumiy kechikishni kamaytiradi.
renderToPipeableStream
funksiyasi React’ning server renderer’ining bir qismi bo’lib, u React ilovasini Node.js oqimiga oqib chiqish orqali streaming usulida uzluksiz uzatishlikni ta’minlash maqsadida render qilishni qo’llab-quvvatlash uchun mo’ljallangan. Bu “Fizz” deb ataladigan server renderer arxitekturasining bir qismidir.
Ushbu bo’limda biz React’ning texnik tafsilotlariga chuqur kirib boramiz va ular vaqt o’tishi bilan o’zgarishi mumkin. Yana bir bor ta’kidlaymizki, bu ta’limiy maqsadlar uchun va o’quvchining qiziqishini qondirish uchundir. O’qiyotgan paytingizda bu React dasturini amalga oshirish tafsilotlariga to’liq mos kelmasligi mumkin, ammo yozish paytida bu qanday ishlashi haqida yaxshi tasavvurga ega bo’lish uchun yetarlicha yaqin. Bu, ehtimol siz foydalanish muhitida ishlatadigan narsa emasdir va React’dan qanday foydalanishni bilish uchun muhim emas, balki bu faqat ta’lim va qiziqish uchundir.
Server render qilish jarayonini umumiy kontekstdan chetga chiqmasdan, qisqacha va sodda qilib tushuntirib o’tamiz:
So’rov(request) yaratish
renderToPipeableStream
funksiyasi kiritish sifatida render qilinishi kerak bo’lgan React elementlarini va ixtiyoriy parametrlar obyektini oladi. Keyin u createRequestImpl
funksiyasi yordamida so’rov obyektini yaratadi. Bu so’rov obyekti React elementlari, resurslar, javob holati va format kontekstini qamrab oladi.
Ishni boshlash
So’rov yaratib bo’lgandan so’ng, startWork
funksiyasi argument sifatida so’rovni qabul qilib, chaqiriladi. Bu funksiya render qilish jarayonini boshlaydi. Render qilish jarayoni asinxron bo’lib, kerak bo’lganda to’xtatilishi va davom ettirilishi mumkin, bu yerda React’ning Suspense xususiyati qo’llaniladi. Agar komponent Suspense hududi bilan o’ralgan bo’lsa va u qandaydir asinxron operatsiyani (masalan, ma’lumotlarni olib kelish) boshlasa, ushbu komponent (va ehtimol uning sheriklari) mazkur operatsiya tugaguncha “to’xtatilishi” mumkin.
Komponent to’xtatilgan paytda u odatda yuklanish indikatori yoki boshqa o’rinbosar kabi “fallback”, ya’ni zaxira, holatda ko’rsatilishi mumkin. Operatsiya tugaganidan so’ng, komponent qayta tiklanadi va yakuniy holatda render qilinadi.
Suspense - bu React’ga server tomonida renderlash paytida asinxron ma’lumotlarni olish va “lazy loading” texnikasi orqali samaraliroq boshqarish imkonini beruvchi kuchli xususiyatdir.
Bu yondashuv orqali foydalanuvchiga darhol mazmunli sahifa ko’rsatish va keyinchalik ma’lumotlar mavjud bo’lganda uni bosqichma-bosqich boyitish imkoniyati yaratiladi. Bu foydalanuvchi bilan ishlash qulayligini yaxshilash uchun qo’llanilishi mumkin bo’lgan samarali texnikadir.
O’tkaziluvchan(pipeable) oqimni qaytarish
renderToPipeableStream
funksiya pipe
va abort
metodlarini o’z ichiga olgan obyektni qaytaradi. pipe
metodi render qilingan natijani yoziladigan oqimga (masalan, Node.js’dagi HTTP javob obyekti) o’tkazish uchun ishlatiladi. abort
metodi esa qolgan barcha I/O operatsiyalarni bekor qilish va barcha qolgan ma’lumotlarni klient tomonidan render qilinadigan rejimga o’tkazish uchun ishlatilishi mumkin.
Belgilangan joy(destination)ga o’tkazish
pipe
metodi belgilangan joy oqimi bilan chaqirilganda, u ma’lumotlar oqimi allaqachon boshlanganini tekshiradi. Agar boshlanmagan bo’lsa, hasStartedFlowing
qiymatini true
ga o’rnatadi va startFlowing
funksiyasini so’rov va belgilangan joy bilan chaqiradi. Shuningdek, belgilangan joy oqimning drain
, error
va close
event’lari uchun ishlov beruvchilarni o’rnatadi.
Oqim hodisa(stream event)larini boshqarish
drain
event’i ishlov beruvchisi belgilangan joy oqimi ko’proq ma’lumotlarni qabul qilishga tayyor bo’lganda ma’lumot oqimini davom ettirish uchun startFlowing
funksiyasini qayta chaqiradi. error
va close
event’lari ishlov beruvchilari belgilangan joy oqimida xatolik yuz berganda yoki oqim muddatidan oldin yopilganda render qilish jarayonini to’xtatish uchun abort
funksiyasini chaqiradi.
Render qilishni bekor qilish
Qaytarilgan obyektning abort
metodi render qilish jarayonini to’xtatish uchun biror sabab bilan chaqirilishi mumkin. Bu react-server
modulidan so’rov va sabab bilan abort
funksiyasini chaqiradi.
react-server
va react-dom
paketlari
Ushbu funksiyalarni haqiqiy implementatsiyasida progressiv render qilish, xatolarni boshqarish va React server renderer’ining qolgan qismi bilan integratsiya kabi murakkabroq logika mavjud. Ushbu funksiyalar uchun kod react-server
va react-dom
paketlarida joylashgan.
renderToPipeableStream
xususiyatlari
renderToPipeableStream
xususiyatlariga quyidagilar kiradi:
- Uzluksiz uzatishlik (Streaming):
renderToPipeableStream
o’tkaziluvchan Node.js oqimini qaytaradi, bu esa uni javob obyektiga o’tkazish imkonini beradi. Bu serverga butun sahifa render qilinmasdan turib HTML’ni klientga yuborishni boshlash imkonini beradi, bu esa katta ilovalar uchun tezroq foydalanuvchi bilan ishlash qulayligini va yaxshiroq ishlashini ta’minlaydi. - Moslashuvchanlik:
renderToPipeableStream
HTML’ni qanday render qilishni yanada ko’proq nazorat qilish imkonini beradi. U boshqa Node.js oqimlari bilan oson integratsiyalashishi mumkin, bu esa dasturchilarga render qilish pipeline’ini moslashtirish va samaraliroq server tomonida render qilish yechimlarini yaratish imkonini beradi. - Suspense’ni qo’llab-quvvatlash:
renderToPipeableStream
React’ning bir vaqtning o’zida bajariladigan(concurrent) xususiyatlarini, jumladan Suspense’ni to’liq qo’llab-quvvatlaydi. Bu dasturchilarga server tomonida render qilish vaqtida asinxron ma’lumotlarni olib kelish va kerakli vaqtda yuklashni yanada samaraliroq boshqarish imkonini beradi, shuningdek, ma’lumotga bog’liq komponentlar faqat zarur ma’lumot mavjud bo’lganda render qilinishini ta’minlaydi.
Qanday moslashadi
Keling, ushbu API’ning afzalliklarini ko’rsatadigan kodga nazar tashlaymiz. Bizda kuchuk zotlari ro’yxatini ko’rsatadigan ilova bor. Ro’yxat API manzilidan ma’lumotlarni olib kelish orqali to’ldiriladi. Ushbu ilova serverda renderToPipeableStream
yordamida render qilinadi va keyin klientga yuboriladi. Avval, kuchuk zotlari ro’yxatini ko’rsatuvchi komponentimizni ko’rib chiqamiz:
const dogResource = createResource(
fetch("https://dog.ceo/api/breeds/list/all")
.then((r) => r.json())
.then((r) => Object.keys(r.message))
);
function DogBreeds() {
return (
<ul>
<Suspense fallback="Loading...">
{dogResource.read().map((profile) => (
<li key={profile}>{profile}</li>
))}
</Suspense>
</ul>
);
}
export default DogBreeds;
Endi esa umumiy App
ni ko’rib chiqamiz, bu DogBreeds
komponentini o’z ichiga oladi:
import React, { Suspense } from "react";
const ListOfBreeds = React.lazy(() => import("./DogBreeds"));
function App() {
return (
<div>
<h1>Dog Breeds</h1>
<Suspense fallback={<div>Loading Dog Breeds...</div>}>
<ListOfBreeds />
</Suspense>
</div>
);
}
export default App;
Diqqat qiling, bu yerda biz React.lazy
dan foydalanmoqdamiz, oldingi boblarda aytilganidek, faqat renderToPipeableStream
Suspense’ni qanday boshqarishini ko’rsatish uchun boshqa Suspense hududini qo’shmoqdamiz. Yaxshi, bularning hammasini birlashtirib, Express serverini yaratamiz:
import express from "express";
import React from "react";
import { renderToPipeableStream } from "react-dom/server";
import App from "./App.jsx";
const app = express();
app.use(express.static("build"));
app.get("/", async (req, res) => {
// Boshlang'ich HTML strukturasini e'lon qilamiz
const htmlStart = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>React Suspense with renderToPipeableStream</title>
</head>
<body>
<div id="root">
`;
// Boshlang'ich HTML’ni javobga yozamiz
res.write(htmlStart);
// React App komponentini renderToPipeableStream bilan chaqiramiz
// va qobiq tayyor bo'lishi uchun options obyektini taqdim etamiz
const { pipe } = renderToPipeableStream(<App />, {
onShellReady: () => {
// Qobiq tayyor bo'lganda render qiligan natijanis javobga uzatamiz
pipe(res);
},
});
});
// Serverni 3000-portda ishga tushiramiz va konsolda xabar yozamiz
app.listen(3000, () => {
console.log("Server is listening on port 3000");
});
Ushbu kod bo’lagi yordamida biz so’rovga HTML oqimini qaytarish orqali javob bermoqdamiz. Biz renderToPipeableStream
yordamida App
komponentimizni oqimga render qilyapmiz va keyin shu oqimni javob obyektimizga uzatmoqdamiz. onShellReady
parametri yordamida qobiq tayyor bo’lgandan keyin oqimni javob obyektiga uzatamiz. Qobiq(Shell) - bu React ilovasi hidratsiya qilinishidan va Suspense hududlarida o’ralgan ma’lumotlarga bo’lgan qaramliklar hal qilinishidan oldin render qilingan HTML qismi. Bizning holatimizda qobiq - bu kuchuk zotlari API’dan olinmasdan oldin render qilingan HTML. Keling, ushbu kodni ishga tushirganda nima sodir bo’lishini ko’rib chiqaylik.
Agar biz http://localhost:3000 ga tashrif buyursak, “Dog Breeds” sarlavhasi va Suspense zaxira “Loading Dog Breeds…” bilan sahifa paydo bo’ladi. Bu - kuchuk zotlari API’dan olingunga qadar render qilingan qobiq (shell). Ajoyib tomoni shundaki, agar HTML kodimizga React’ni qo’shmasak ham va sahifani hidratsiya qilmasak ham, Suspense zaxirasi o’rniga haqiqiy kuchuk zotlari API’dan kelgach avtomatik ravishda joylashtiriladi. Ma’lumotlar mavjud bo’lganda DOM’ni almashtirish klient tomonidagi React ishtirokisiz to’liq server tomonidan amalga oshiriladi!
Bu qanday ishlashini batafsil tushunamiz
Yana bir bor aytib o’tamiz, biz bu yerda React implementatsiyasi tafsilotlariga chuqur kiryapmiz, lekin bu tafsilotlar vaqt o’tishi bilan o’zgarishi mumkin. Bu mashqning (va bu kitobning) maqsadi alohida implementatsiya tafsilotlariga ko’p urg’u berish emas, balki React’ning asosiy mexanizmini tushunib olishdir. Bu mexanizmni tushunish orqali biz React’ni yaxshiroq tushunamiz va o’z kunlik ishimizda amaliy vositalarga ega bo’lamiz.
Agar http://localhost:3000 ga tashrif buyursak, server “Dog Breeds” sarlavhasi va Suspense zaxira “Loading Dog Breeds…” bilan HTML qobiqqa javob beradi. Ushbu HTML quyidagicha ko’rinadi:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>React Suspense with renderToPipeableStream</title>
</head>
<body>
<div id="root">
<div>
<h1>Dog Breeds</h1>
<!--$?--><template id="B:0"></template>
<div>Loading dog breeds...</div>
<!--/$-->
</div>
<div hidden id="S:0">
<ul>
<!--$-->
<li>affenpinscher</li>
<li>african</li>
<li>airedale</li>
[...]
<!--/$-->
</ul>
</div>
<script>
function $RC(a, b) {
a = document.getElementById(a);
b = document.getElementById(b);
b.parentNode.removeChild(b);
if (a) {
a = a.previousSibling;
var f = a.parentNode,
c = a.nextSibling,
e = 0;
do {
if (c && 8 === c.nodeType) {
var d = c.data;
if ("/$" === d)
if (0 === e) break;
else e--;
else ("$" !== d && "$?" !== d && "$!" !== d) || e++;
}
d = c.nextSibling;
f.removeChild(c);
c = d;
} while (c);
for (; b.firstChild; ) f.insertBefore(b.firstChild, c);
a.data = "$";
a._reactRetry && a._reactRetry();
}
}
$RC("B:0", "S:0");
</script>
</div>
</body>
</html>
Bu yerda qiziqarli holatni ko’rishimiz mumkin. <template>
elementini yaratilgan ID bilan (bu holda B:0
) va HTML izohlari mavjud. Ushbu HTML izohlari qobiqning boshlanish va tugash joylarini belgilaydi. Ular Suspense hal qilingandan keyin ma’lumotlar joylashtiriladigan belgilar yoki “bo’sh joylar” sifatida ishlaydi. HTML’dagi <template>
elementlari, DOM iyerarxiyasida qo’shimcha darajani yaratmasdan, dokument subdaraxtlarini yaratish va tugunlarni ushlab turish imkonini beradi. Ular tugunlar guruhlarini boshqarish uchun yengil konteyner bo’lib xizmat qiladi, DOM manipulyatsiyasi paytida bajarilgan ish hajmini kamaytirish orqali ish faoliyatini yaxshilaydi.
Shuningdek, <script>
elementi mavjud. Ushbu <script>
tegida $RC
deb nomlangan funksiya mavjud bo’lib, u qobiqni haqiqiy kontent bilan almashtirish uchun ishlatiladi. $RC
funksiyasi ikkita argumentni qabul qiladi: markerni o’z ichiga olgan <template>
elementining ID’si va zaxirani o’z ichiga olgan <div>
elementining ID’si. Funksiya, ma’lumotlar mavjud bo’lgandan keyin, markerni render qilingan UI bilan to’ldiradi va zaxirani olib tashlaydi.
Ushbu funksiyaning minimallashtirilganligi unchalik qulay emas, lekin uni qayta ochishga va nima qilayotganini tushunishga harakat qilaylik. Agar biz shunday qilsak, quyidagi kodni ko’ramiz:
function reactComponentCleanup(reactMarkerId, siblingId) {
let reactMarker = document.getElementById(reactMarkerId);
let sibling = document.getElementById(siblingId);
sibling.parentNode.removeChild(sibling);
if (reactMarker) {
reactMarker = reactMarker.previousSibling;
let parentNode = reactMarker.parentNode,
nextSibling = reactMarker.nextSibling,
nestedLevel = 0;
do {
if (nextSibling && 8 === nextSibling.nodeType) {
let nodeData = nextSibling.data;
if ("/$" === nodeData) {
if (0 === nestedLevel) {
break;
} else {
nestedLevel--;
}
} else if ("$" !== nodeData && "$?" !== nodeData && "$!" !== nodeData) {
nestedLevel++;
}
}
let nextNode = nextSibling.nextSibling;
parentNode.removeChild(nextSibling);
nextSibling = nextNode;
} while (nextSibling);
while (sibling.firstChild) {
parentNode.insertBefore(sibling.firstChild, nextSibling);
}
reactMarker.data = "$";
reactMarker._reactRetry && reactMarker._reactRetry();
}
}
reactComponentCleanup("B:0", "S:0");
Ushbu funksiyani tahlil qilamiz
Funksiya ikkita argumentni qabul qiladi: reactMarkerId
va siblingId
. Aniqrog’i, marker bu - render qilingan komponentlar mavjud bo’lganda joylashtiriladigan bo’shliqdir, va sibling(qo’shni element) bu - Suspense fallback, ya’ni zaxira xabaridir.
Funksiya removeChild
metodidan foydalanib, ma’lumotlar mavjud bo’lganda DOM’dan qo’shni elementni (fallback’ni) olib tashlaydi.
Agar reactMarker
elementi mavjud bo’lsa, funksiya ishga tushadi. Bu funksiya reactMarker
o’zgaruvchisini hozirgi reactMarker
elementining oldingi qo’shni elementiga o’rnatadi. Funksiya, shuningdek, parentNode
, nextSibling
va nestedLevel
o’zgaruvchilarini ham ishga tushiradi.
do...while
sikli DOM daraxtini kesib o’tish uchun ishlatiladi, va bu nextSibling
elementdan boshlanadi. Sikl davom etadi, toki nextSibling
elementi mavjud bo’lsa. Sikl ichida funksiya nextSibling
elementining izoh tuguni (nodeType
qiymati 8 ko’rsatilgan) ekanligini tekshiradi:
- Agar
nextSibling
elementi izoh tuguni bo’lsa, funksiya uning ma’lumotlarini (ya’ni, izoh matnini) tekshiradi. Bu ma’lumot"/$"
ga teng bo’lsa, bu ichma-ich strukturaning oxirini bildiradi. AgarnestedLevel
qiymati0
bo’lsa, sikl tugaydi, ya’ni kerakli struktura oxiri topilgan bo’ladi. AgarnestedLevel
qiymati0
bo’lmasa, bu"/$"
izoh tuguni ichma-ich strukturaning bir qismi ekanligini anglatadi vanestedLevel
qiymati kamayadi. - Agar izoh tugunidagi ma’lumot
"/$"
ga teng bo’lmasa, funksiya uning"$"
,"$?"
, yoki"$!"
ekanligini tekshiradi. Bu qiymatlar yangi ichma-ich strukturaning boshlanishini bildiradi. Agar ushbu qiymatlardan birontasi topilsa,nestedLevel
qiymati oshadi.
Har bir iteratsiyada nextSibling
elementi (ya’ni, Suspense hududi) removeChild
metodidan foydalanib uning ota tugunidan olib tashlanadi. Sikl davom etadi va DOM daraxtidagi keyingi qo’shni elementi bilan davom etadi.
Sikl tugallangandan so’ng, funksiya qo’shni elementining barcha bolalarini DOM daraxtida nextSibling
elementining oldiga ko’chiradi va bunda insertBefore
metodidan foydalanadi. Bu jarayon DOM’ni reactMarker
elementi atrofida qayta tuzadi va Suspense zaxirasini o’rab turgan komponent bilan almashtiradi.
Shundan so’ng, funksiya reactMarker
elementining ma’lumotini "$"
ga o’rnatadi, bu ehtimol keyinchalik ishlov berish yoki murojaat qilish uchun komponentni belgilash uchun ishlatiladi. Agar reactMarker
elementida reactRetry
xususiyati mavjud bo’lsa va u funksiya bo’lsa, funksiya ushbu metodni chaqiradi.
Agar ba’zi qismni tushunish qiyin bo’lgan bo’lsa, xavotir olmang. Bularni qisqacha umumlashtirsak: bu funksiya React komponentlari ma’lumotga bog’liq bo’lganda ularga tayyor bo’lishini kutadi va tayyor bo’lgach, Suspense fallback(zaxira)’larini serverda render qilingan komponentlarga almashtiradi. Bu izoh tugunlarini aniq ma’lumot qiymatlari bilan ishlatadi va shu orqali komponentlar strukturasini aniqlaydi hamda DOM’ni shu asnoda manipulyatsiya qiladi. Bu HTML’da server tomonidan qo’shilgani uchun, renderToPipeableStream
yordamida ma’lumotlarni shunday oqimda uzatishimiz va brauzer React’ni bog’lamasdan yoki hidratsiya qilmasdan UI’ni mavjud bo’lganda ko’rsatishi mumkin.
Shunday qilib, renderToPipeableStream
bizga serverda render qilishda renderToString
ga nisbatan ancha ko’proq nazorat qilish imkoniyatini va quvvatni beradi.