Fiber reconciliation
Fiber reconciliation ikki bosqichda amalga oshiriladi: *render(tayyorlash) *bosqichi va commit(o’zgarishlarni tatbiq qilish) bosqichi. Ushbu ikki bosqichli yondashuv (rasmda ko’rsatilgan) React’ga, DOM’ga qo’shilishdan va foydalanuvchilarga yangi holatni ko’rsatishdan oldin har qanday vaqtda bekor qilinishi mumkin bo’lgan renderlash ishini bajarish imkonini beradi: bu renderlashni to’xtatib qo’yadigan qiladi. Biroz batafsilroq aytadigan bo’lsak, renderlashni to’xtatib qo’yadigan narsa bu React rejalashtiruvchisi(scheduler) tomonidan har 5 msda bajarishni asosiy thread(main thread)ga qaytarishning g’ayrioddiy yondashuvi bo’lib, bu hatto 120 fps (kadr/sekund) tezlikdagi qurilmalarda ham bitta kadrlashdan kichikroqdir.
Biz kelgusi boblarda React’ning concurrent(bir vaqtda ishlashlik) xususiyatlarini o’rganayotganda scheduler’ning tafsilotlariga chuqurroq kiramiz. Ammo hozircha, reconciliation’ning ushbu bosqichlarini ko’rib chiqamiz.
Render bosqichi (render phase)
Render bosqichi joriy daraxtda state o’zgarishi hodisasi sodir bo’lganda boshlanadi. React o’zgarishlarni alternativ daraxtda, ekrandan tashqarida, har bir Fiber’ni rekursiv ravishda bosqichma-bosqich ko’rib chiqish va yangilanishlar kutilayotganligini bildiruvchi bayroqlarni o’rnatish orqali amalga oshiradi (rasmga qarang). Yuqorida aytib o’tilganidek, bu jarayon React ichida beginWork
deb nomlangan funksiyada sodir bo’ladi.
beginWork
beginWork
hali ish jarayonida bo’lgan(in-progress) daraxtdagi Fiber tugunlarida ular yangilanishi kerakmi yoki yo’qligini bildiruvchi bayroqlarni o’rnatish uchun javobgardir. Bu bir nechta bayroqlarni o’rnatadi va keyin navbatdagi Fiber tugunga o’tib, daraxtning oxiriga yetguncha shu ishni davom ettiradi. Bu tugagandan so’ng, Fiber tugunlarida completeWork
funksiyasi chaqirila boshlanadi va yuqoriga qarab harakat qilinadi.
beginWork
funksiyasining ko’rinishi quyidagicha:
function beginWork(
current: Fiber | null,
workInProgress: Fiber,
renderLanes: Lanes
): Fiber | null;
completeWork
haqida keyinroq batafsil ma’lumot beriladi. Hozircha, beginWork
funksiyasini ko’rib chiqamiz. Uning ko’rinishida quyidagi argumentlar mavjud:
current
Joriy daraxtdagi hali ish jarayonida bo’lgan tugunga mos keladigan Fiber tuguniga havola. Bu daraxtning avvalgi va yangi versiyasi o’rtasida qanday o’zgarishlar bo’lganligini aniqlash va nimalarni yangilash kerakligini belgilash uchun ishlatiladi. Bu hech qachon o’zgartirilmaydi va faqat taqqoslash uchun ishlatiladi
workInProgress
Hali ish jarayonida bo’lgan yangilanayotgan Fiber tuguni. Bu tugun yangilangan taqdirda “ifloslangan” deb belgilanadi va funksiya tomonidan qaytariladi.
renderLanes
Render lanes(render yo’llari) — bu React’ning Fiber reconciler’ida yangi tushuncha bo’lib, eski renderExpirationTime
ni o’rnini egallaydi. Bu eski renderExpirationTime
tushunchasiga nisbatan biroz murakkabroq, ammo React’ga yangilanishlarni yaxshiroq ustuvorlashtirish va yangilanish jarayonini samaraliroq qilish imkonini beradi. renderExpirationTime
eskirganligi sababli, biz bu bobda renderLanes
ga e’tibor qaratamiz.
Render yo’l(lane)lari asosan yangilanishlar ishlov berilayotgan “yo’l(lane)lar”ni ifodalovchi bitmask’dir. Yo’llar yangilanishlarni ularning ustuvorligi va boshqa omillar asosida tasniflashning bir usulidir. React komponentida o’zgarish amalga oshirilganda, bu o’zgarish uning ustuvorligi va boshqa xususiyatlariga qarab bir yo’lga tayinlanadi. O’zgarishning ustuvorligi yuqori bo’lsa unga yuqori yo’l, ya’ni lane, beriladi.
Yangilanishlar to’g’ri tartibda ishlanishini ta’minlash uchun renderLanes
qiymati beginWork
funksiyasiga uzatiladi. Yuqori ustuvorlikka ega yo’llarga tayinlangan yangilanishlar, past ustuvorlikka ega yo’llarga tayinlangan yangilanishlardan avval ishlov beriladi. Bu, foydalanuvchi bilan interaktivlik yoki foydalanish imkoniyati qulayligi(accessibility) kabi yuqori ustuvorlikdagi yangilanishlarning iloji boricha tezroq ishlov berilishini ta’minlaydi.
Yangilanishlarni ustuvorlashtirishdan tashqari, renderLanes
React’ga konkurentlikni, ya’ni bir vatda ishlashni, yaxshiroq boshqarishga ham yordam beradi. React uzun davom etadigan yangilanishlarni kichik, boshqarish oson bo’lgan bo’laklarga ajratish uchun “vaqtni bo’lish”(time slicing) deb ataladigan texnikadan foydalanadi. renderLanes
bu jarayonda muhim rol o’ynaydi, chunki bu React’ga qaysi yangilanishlar birinchi bo’lib ishlov berilishi kerakligini va qaysi yangilanishlar keyinroqqa kechiktirilishi mumkinligini aniqlash imkonini beradi.
Render bosqichi tugagach, getLanesToRetrySynchronouslyOnError
funksiyasi render bosqichida qachondir kechiktirilgan yangilanishlar yaratilganligini aniqlash uchun chaqiriladi. Agar kechiktirilgan yangilanishlar bo’lsa, updateComponent
funksiyasi yangi ish siklini boshlaydi, beginWork
va getNextLanes
dan foydalanib, yangilanishlarni ishlov berish va ularni yo’llariga ko’ra ustuvorlashtirish uchun.
Biz “Render Lane”’lar haqida kelgusi bobda yanada chuqurroq o’rganamiz. Hozircha, Fiber reconciler oqimini davom ettiraylik.
completeWork
completeWork
funksiyasi hali tugallanmagan bo’lgan Fiber tuguniga yangilanishlarni qo’llaydi va ilovaning yangilangan holatini ifodalovchi yangi real DOM daraxtini yaratadi. Ushbu daraxt brauzer ko’rinishidan tashqarida, DOM bilan bog’lanmagan holda quriladi.
Agar asosiy muhit brauzer bo’lsa, bu document.createElement
yoki newElement.appendChild
kabi ishlarni bajarishni anglatadi. Yodda tuting, ushbu elementlar daraxti hali brauzerdagi dokument bilan bog’lanmagan: React shunchaki UI’ning navbatdagi versiyasini ekran tashqarisida yaratmoqda. Bu ishni ekran tashqarisida bajarish uni to’xtatiluvchan qiladi: React hisoblayotgan navbatdagi holat hali ekranga chizilmagan, shuning uchun yuqori ustuvorlikka ega yangilanish rejalashtirilsa, uni bekor qilish mumkin. Bu Fiber reconciler’ning asosiy maqsadi.
completeWork
funksiyasining tuzilishi quyidagicha:
function completeWork(
current: Fiber | null,
workInProgress: Fiber,
renderLanes: Lanes
): Fiber | null;
Bu yerda, beginWork
bilan bir xil tuzilish mavjud.
completeWork
funksiyasi beginWork
funksiyasiga yaqin bo’lib, beginWork
Fiber tugunidagi “yangilanish kerakmi” holati haqida bayroqlarni o’rnatish uchun javobgar bo’lsa, completeWork
yangi daraxtni yaratib, uni asosiy host muhitga kiritish uchun javobgardir. completeWork
yuqoriga yetib, yangi DOM daraxtini yaratgandan so’ng, “render bosqichi tugallandi” deb aytiladi. Endi React commit bosqichiga o’tadi.
Commit bosqichi (commit phase)
Commit(tatbiq qilish) bosqichi (rasmga qarang) real DOM’ni render bosqichida virtual DOM’ga kiritilgan o’zgarishlar bilan yangilash uchun javobgardir. Commit bosqichi davomida yangi virtual DOM daraxti asosiy host muhitga kiritiladi va hali tugallanmagan daraxt joriy daraxt bilan almashtiriladi. Shu bosqichda barcha effektlar ham bajariladi. Commit bosqichi ikki qismga bo’linadi: mutatsiya bosqichi va layout bosqichi.
Mutatsiya bosqichi (mutation phase)
Mutatsiya bosqichi — bu commit, ya’ni tatbiq qilish, qo’llash, bosqichining birinchi qismi bo’lib, virtual DOM’ga kiritilgan o’zgarishlarni real DOM’ga yangilash uchun javobgardir. Ushbu bosqichda React yangilanishlar kerakligini aniqlaydi va commitMutationEffects
deb nomlangan maxsus funksiyani chaqiradi. Bu funksiya render bosqichida alternativ daraxtdagi Fiber tugunlariga kiritilgan o’zgarishlarni real DOM’ga qo’llaydi.
Bu yerda, commitMutationEffects
qanday amalga oshirilishi mumkinligini to’liq psevdokod misolida ko’rsatamiz:
function commitMutationEffects(Fiber) {
switch (Fiber.tag) {
case HostComponent: {
// DOM tugunini yangi props va/yoki children bilan yangilash
break;
}
case HostText: {
// DOM tugunining tekst kontentini yangilash
break;
}
case ClassComponent: {
// Lifecycle metodlari, masalan, componentDidMount va componentDidUpdate chaqiriladi
break;
}
// ... boshqa turdagi tugunlar uchun holatlar
}
}
Mutatsiya bosqichi davomida React shuningdek, commitUnmount
va commitDeletion
kabi maxsus funksiyalarni ham chaqiradi, bu funksiyalar DOM’dan endi kerak bo’lmagan tugun(node)larni olib tashlash uchun ishlatiladi.
Layout bosqichi (layout phase)
Layout(joylashuv) bosqichi — commit bosqichining ikkinchi qismi bo’lib, DOM’dagi yangilangan tugunlarning yangi joylashuvlarini hisoblash uchun mas’uldir. Ushbu bosqichda React commitLayoutEffects
deb nomlangan maxsus funksiyani chaqiradi. Bu funksiya DOM’dagi yangilangan tugunlarning yangi joylashuvlarini hisoblab chiqadi.
commitMutationEffects
kabi, commitLayoutEffects
ham turli tugunlar yangilanishiga qarab har xil funksiyalarni chaqiradigan katta “switch statement”ga ega.
Layout bosqichi yakunlangandan so’ng, React real DOM’ni render bosqichida virtual DOM’ga kiritilgan o’zgarishlarga mos ravishda muvaffaqiyatli yangilaydi.
Commit bosqichini ikki qismga — mutatsiya va layout’larga ajratish orqali React DOM’ga yangilanishlarni samarali tarzda qo’llaydi. Reconciler’dagi boshqa asosiy funksiyalar bilan hamkorlikda ishlash orqali commit bosqichi React ilovalari murakkablashib, katta miqdordagi ma’lumotlarni qayta ishlashiga qaramay, tez, javob beruvchan va ishonchli bo’lishini ta’minlaydi.
Effektlar (effects)
React’ning reconciliation jarayonining commit bosqichida “side effect”lar o’ziga xos tartibda, effektning turiga qarab bajariladi. Commit bosqichida sodir bo’lishi mumkin bo’lgan bir nechta effektlar mavjud:
- Joylashtirish effektlari (Placement effects): Bu effektlar yangi komponent DOM’ga qo’shilganda yuz beradi. Masalan, agar forma ichiga yangi tugma(button) qo’shilsa, tugmani DOM’ga qo’shish uchun ushbu joylashtirish effekti sodir bo’ladi.
- Yangilash effektlari (Update effects): Bu effektlar komponent yangi props yoki state bilan yangilanganda yuz beradi. Masalan, agar tugmaning teksti o’zgarsa, tekstni DOM’da yangilash uchun yangilash effekti sodir bo’ladi.
- O’chirish effektlari (Deletion effects): Bu effektlar komponent DOM’dan o’chirilganda yuz beradi. Masalan, agar forma ichidagi tugma olib tashlansa, tugmani DOM’dan olib tashlash uchun o’chirish effekti sodir bo’ladi.
- Layout(joylashuv) effektlari (Layout effects): Bu effektlar brauzer ekranga chizish imkoniyatiga ega bo’lmasdan oldin sodir bo’ladi va sahifaning joylashuvi, ya’ni layout’ini, yangilash uchun ishlatiladi. Layout effektlari funksional komponentlarda
useLayoutEffect
hook’i va class komponentlardacomponentDidUpdate
lifecycle metodi orqali boshqariladi.
Commit bosqichidagi ushbu effektlardan farqli o’laroq, passiv effektlar ham mavjud. Passiv effektlar — bu foydalanuvchi tomonidan belgilanadigan effektlar bo’lib, brauzer ekranga chizish imkoniyatiga ega bo’lgandan keyin bajariladi. Passiv effektlar useEffect
hook’i orqali boshqariladi.
Passiv effektlar sahifaning dastlabki chizilishida muhim bo’lmagan harakatlarni amalga oshirish uchun foydalidir, masalan, API’dan ma’lumot olish yoki analitika kuzatuvini amalga oshirish. Passiv effektlar render bosqichida bajarilmaganligi sababli, foydalanuvchi interfeysini dasturchi istagan holatga olib kelish uchun minimal yangilanishlar to’plamini hisoblash vaqtiga ta’sir qilmaydi.
Hamma narsani ekranga chiqarish
React ikkita daraxtdan biriga ishora qiluvchi FiberRootNode
deb nomlangan yuqori darajadagi tugunni boshqaradi: bu current
yoki workInProgress
daraxtlari bo’lishi mumkin. FiberRootNode
— reconciliation jarayonining commit bosqichini boshqarish uchun javob beradigan muhim ma’lumotlar strukturasi hisoblanadi.
Virtual DOM’ga o’zgarishlar kiritilganda, React workInProgress
daraxtini yangilaydi, lekin current
daraxtini o’zgarishsiz qoldiradi. Bu React’ga virtual DOM’ni render qilish va yangilashni davom ettirish imkonini beradi, shu bilan birga dastur holatining hozirgi holatini saqlaydi.
Render jarayoni tugagach, React commitRoot
deb nomlangan funksiyani chaqiradi, bu funksiya workInProgress
daraxtida amalga oshirilgan o’zgarishlarni real DOM’ga kiritish uchun javobgardir. commitRoot
funksiyasi FiberRootNode
ko’rsatkich ishorasi(pointer)ni joriy daraxtdan workInProgress
daraxtiga o’zgartiradi, natijada workInProgress
daraxti yangi joriy daraxt bo’lib qoladi.
Shundan so’ng, kelgusidagi barcha yangilanishlar yangi joriy daraxtga asoslanadi. Bu jarayon dastur holatining izchil qolishini va o’zgarishlarning to’g’ri va samarali tarzda qo’llanilishini ta’minlaydi.
Bularning barchasi brauzerda deyarli darhol sodir bo’lgandek tuyuladi. Bu — “reconciliation jarayoni”ning natijasidir.