Mundarija (30)
- Bu darsda
- 1. Nega bu kerak?
- 2. React DevTools Profiler
- 2.1 Yozib olish
- 2.2 Commit'lar va flamegraph
- 2.3 Ranked va "Why did this render?"
- 3. <Profiler> API
- 3.1 Koddan o'lchash
- 3.2 onRender argumentlari
- 3.3 nested-update
- 3.4 Production'da ishlamaydi
- 4. Chrome Performance Tracks
- 4.1 React 19.2 dagi yangilik
- 4.2 Trekdagi hodisalar
- 5. Boshqa vositalar
- 6. Vazifalar qadami: profiling build va <Profiler> (holat 22)
- 6.1 Reja
- 6.2 vite.config.ts: ikki joy
- 6.3 profil.ts va App.tsx
- 6.4 O'lchov
- 6.5 Tekshiruvlar va commit
- 7. Ko'p uchraydigan xatolar
- 8. Mashqlar
- 1-mashq (oson): qaysi vosita?
- 2-mashq (o'rta): commit'larni sanash
- 3-mashq (qiyin): nested-update ni yo'qoting
- 4-mashq: vazifalar — o'z o'lchovingiz
- 9. Real ishda
- Xulosa
- Manbalar
Performance'ni o'lchash: Profiler va Performance Tracks
Qisqacha: Taxmin emas — o'lchov. React'da uch asosiy vosita bor. React DevTools Profiler — yozib olasiz va har commit uchun qaysi komponent qancha ms chizilganini ko'rasiz (flamegraph), "Why did this render?" sababini ham. Ikkinchisi
<Profiler id onRender>— koddan o'lchov:actualDuration(shu commit'dagi haqiqiy ish) vabaseDuration(memo'siz hammasini chizish taxmini). Performance Tracks (React 19.2) — Chrome Performance panelidaScheduler ⚛(Blocking, Transition, Suspense, Idle) vaComponents ⚛treklari. Production build'da ularning hech biri ishlamaydi — buning uchunreact-dom/profiling.vazifalarda 10 000 vazifa bilan bitta katak:actualDuration8.8 ms,baseDuration54.8 ms —memoishini raqamda ko'ramiz.
Bu darsda
- React DevTools Profiler'da yozib olish, commit tanlash, flamegraph va ranked ko'rinishini o'qiysiz.
<Profiler>API'si vaonRenderargumentlarini (phase,actualDuration,baseDuration) ishlatasiz.- Chrome Performance panelidagi React treklarini taniysiz.
- Production'da o'lchash uchun profiling build yasaysiz.
- react-scan va why-did-you-render qachon foydali ekanini bilasiz.
Oldin bilishingiz kerak: React DevTools bilan ishlash, Qayta render sabablari va miflar, memo, useMemo, useCallback, Core Web Vitals.
1. Nega bu kerak?
Oxirgi olti darsda biz ko'p raqam ishlatdik: 18 056 render, 48 ms, 264 ms, 6.6 KB. Ularni kanondagi maxsus skriptlar o'lchagan — puppeteer, React DevTools hook'ining o'rinbosari, Event Timing. O'quvchi sifatida siz har safar shunday skript yozmaysiz. Kundalik ishda "nega sekin?" savoliga javob — standart vositalar.
Ikkinchi sabab: "sekin" bir necha xil bo'ladi. Render uzoq (komponentlar ko'p yoki og'ir). Commit uzoq (DOM katta). Paint uzoq (CSS va joylashuv). Yoki React umuman aybdor emas — asosiy oqimni boshqa skript band qilgan. Har biriga boshqa davo, va davolashdan oldin qaysi biri ekanini aniq bilish kerak.
Hayotiy o'xshatish: Jasur aka "oshxonada buyurtma sekin chiqyapti" deydi. Sabab oshpazdami, ofitsiantdami yoki kassadami? Har bosqichni soat bilan o'lchamaguncha, kimni o'rgatish kerakligini bilmaysiz. Profiler — o'sha soat.
2. React DevTools Profiler
2.1 Yozib olish
React DevTools darsida Profiler yorlig'iga bir ko'z tashlagan edik. Endi tartib bilan:
- Settings → Profiler: "Record why each component rendered while profiling" ni yoqing.
- Profiler yorlig'ida ko'k doira — yozishni boshlang.
- Ilovada bitta harakat qiling (bitta bosish, bitta harf).
- Doirani qayta bosing — to'xtating.
Bitta harakat — bitta yozuv. Uzoq yozuvda o'nlab commit aralashib ketadi va asosiysini topish qiyin bo'ladi.
2.2 Commit'lar va flamegraph
Yuqori o'ng burchakda — ustunlar qatori: har ustun bitta commit (Render va commit). Ustun balandligi — shu commit'ning davomiyligi, rangi — sariq (uzoq) dan ko'k-yashil (qisqa) gacha. Bitta katak bosilganda vazifalar da beshta ustun bo'ladi — optimistik yangilanish, server javobi, tasdiq (Qayta render sabablari dagi "5 commit").
Ustunni tanlang — pastda shu commit'ning flamegraphi (alanga grafigi) chiqadi: komponentlar daraxti gorizontal chiziqlar ko'rinishida. Ota tepada, bolalar ostida. O'qish qoidasi:
| Ko'rinish | Ma'nosi |
|---|---|
| chiziq kengligi | komponent va bolalarini chizish vaqti |
| sariq / to'q rang | ko'p vaqt oldi |
| ko'k-yashil | kam vaqt oldi |
| kulrang, chiziqli | shu commit'da chizilmadi ("Did not render") |
memo ishlayotganini flamegraph'da darhol ko'rasiz: memo, useMemo, useCallback dagi holat 20 da katak bosilganda 1 000 qatordan bittasi rangli, qolganlari kulrang.
2.3 Ranked va "Why did this render?"
Ranked (tartiblangan) ko'rinish — o'sha commit'dagi komponentlar faqat o'z vaqti bo'yicha (bolalarisiz), eng sekini tepada. "Qaysi bitta komponent og'ir?" savoliga eng tez javob shu.
Komponentni bosing — o'ng panelda:
- "Why did this render?" — Qayta render sabablari dagi uchta sababdan biri: "The parent component rendered.", "• Hook 1 changed", "• Context changed". Yana "• Props changed:" (yonida props nomi) va birinchi chizishda "This is the first time the component rendered." chiqishi mumkin.
- "Rendered at" — yozuv davomida bu komponent qaysi commit'larda chizilgani. Bitta harakatda 5 marta chizilgan komponent — shubhali.
Sozlamalardagi yana bir foydali joy — "Hide commits below N ms": mayda commit'larni yashirib, katta ishni topish oson.
Tekshirib ko'ring: Flamegraph'da
VazifaRoyxatisariq va keng, uning ostidagi 1 000 qatorning hammasi rangli. Ranked'da eng tepadaAmalTugmasi— har biri 0.1 ms. MuammoAmalTugmasidami?
Javob
Yo'q. Bitta AmalTugmasi arzon, muammo — soni: 2 000 ta tugma × 0.1 ms. Ranked ko'rinishi har komponentni alohida ko'rsatgani uchun "eng sekin" deyarli teng mayda bo'laklarga bo'linib ketadi. Flamegraph esa butun ro'yxat qismi og'irligini ko'rsatadi. Savol "nega 1 000 qator chizildi?" — ya'ni VazifaQatori ning "Why did this render?" ga qarash kerak.
3. <Profiler> API
3.1 Koddan o'lchash
DevTools — qo'lda. Testda, CI'da yoki foydalanuvchi kompyuterida o'lchash uchun React'da komponent bor: <Profiler> — daraxtning bir qismini o'raydi va har commit'da onRender funksiyasini chaqiradi.
import { Profiler, useState } from "react";
function onRender(id, phase, actualDuration, baseDuration) {
console.log(id, phase, actualDuration >= 0, baseDuration >= 0);
}
function Menu({ count }) {
return <p>Buyurtmalar: {count}</p>;
}
function App() {
const [count, setCount] = useState(0);
return (
<Profiler id="App" onRender={onRender}>
<button onClick={() => setCount(count + 1)}>+1</button>
<Profiler id="Menu" onRender={onRender}>
<Menu count={count} />
</Profiler>
</Profiler>
);
}Konsolda:
Menu mount true true
App mount true true
Menu update true true
App update true trueVaqtlarni konsolga son sifatida chiqarmadik: ular har kompyuterda va har urinishda boshqacha. Bu yerda faqat ular borligi va manfiy emasligi ko'rinadi. «Ishga tushir» da console.log(id, phase, actualDuration) deb o'zgartirib ko'ring — o'z kompyuteringiz raqamlarini ko'rasiz.
Ikki narsaga e'tibor bering. Birinchisi — tartib: ichki Menu oldin, tashqi App keyin, xuddi effektlardagidek (bola → ota). Ikkinchisi — Profiler ichma-ich bo'lishi mumkin: har biri o'z qismini o'lchaydi.
3.2 onRender argumentlari
| Argument | Ma'nosi |
|---|---|
id |
<Profiler id> dagi nom |
phase |
"mount" (birinchi), "update" yoki "nested-update" |
actualDuration |
shu commit'da o'ralgan daraxtni chizishga ketgan ms (memo bilan o'tkazilganlar kirmaydi) |
baseDuration |
hamma komponentlarning oxirgi render vaqtlari yig'indisi — memo siz chizilsa, qancha ketardi |
startTime, commitTime |
render boshlangan va commit qilingan payt (performance.now() shkalasi) |
Eng foydali juftlik — actualDuration va baseDuration. Ular yaqin bo'lsa — daraxt deyarli to'liq qayta chizilgan. actualDuration ancha kichik bo'lsa — memo yoki kompozitsiya ishni tejagan. Farq — tejalgan ish.
3.3 nested-update
Uchinchi faza — nested-update: commit tugashi bilan useLayoutEffect (yoki ref callback) ichida setState chaqirilsa, React yangi renderni darhol, paint'dan oldin bajaradi (useLayoutEffect). Bu ikkinchi commit sinxron, foydalanuvchi esa birinchisini ko'rmaydi:
import { Profiler, useLayoutEffect, useState } from "react";
function onRender(id, phase) {
console.log(id, phase);
}
function Price({ value }) {
const [label, setLabel] = useState("");
useLayoutEffect(() => {
setLabel(`${value} so'm`); // ❌ hosilaviy qiymat effektda
}, [value]);
return <p>{label}</p>;
}
function App() {
return (
<Profiler id="Price" onRender={onRender}>
<Price value={35000} />
</Profiler>
);
}Konsolda:
Price mount
Price nested-updateBirinchi chizishda ikki commit: avval bo'sh <p>, keyin matn bilan. nested-update — Profiler'dagi ogohlantiruvchi belgi: "bu yerda qo'shimcha sinxron commit bor". Ba'zan u zarur (DOM o'lchab, tooltip joylashtirish), lekin bu misolda emas — label render paytida hisoblanadi (Sizga effekt kerak emas). Tuzatish — 3-mashqda.
3.4 Production'da ishlamaydi
<Profiler> ning onRender i faqat dev build'da va maxsus profiling build'da chaqiriladi. Oddiy production build'da React vaqt o'lchash kodini butunlay olib tashlaydi — onRender jim, xarajat ham nol. Shuning uchun <Profiler> ni kodda qoldirish xavfsiz.
Lekin dev build ham o'lchov uchun yomon: u production'dan bir necha barobar sekin (qo'shimcha tekshiruvlar, StrictMode). Haqiqiy raqam uchun — production'ning o'zi, lekin profiling yoqilgan. react-dom paketida buning uchun alohida kirish bor: react-dom/profiling (React 19.3.0 da cjs/react-dom-profiling.profiling.js). Uni qanday ulash — «Vazifalar qadami» da.
4. Chrome Performance Tracks
4.1 React 19.2 dagi yangilik
Chrome DevTools'ning Performance paneli butun brauzerni yozadi: JavaScript, uslub hisobi, layout, paint, tarmoq (Core Web Vitals). Uzoq vaqt React u yerda faqat "qandaydir JavaScript funksiyalari" bo'lib ko'rinardi. React 19.2 (2025-10-01) panelga o'z treklarini qo'shdi — Performance Tracks.
Ular dev build'da va profiling build'da yoziladi (console.timeStamp orqali). Ikki guruh:
- Scheduler — React nima bilan band: qaysi ustuvorlikda ish ketyapti.
- Components — qaysi komponent qancha vaqt chizildi (flamegraph'ning vaqt chizig'idagi ko'rinishi).
flowchart TD
P["Chrome Performance paneli"] --> S["Scheduler ⚛"]
P --> C["Components ⚛"]
S --> B["Blocking: bosish, yozish"]
S --> G["Gesture"]
S --> T["Transition: startTransition, Action"]
S --> SU["Suspense: qayta urinish"]
S --> I["Idle"]
C --> K["Komponentlar: render vaqti"]Diagrammadagi Scheduler ⚛ bolalariga qarang — bu Reconciliation darsidagi lanes guruhlari. react-dom 19.3.0 kodida trek nomi yo'lak bitlaridan tanlanadi: lanes & 63 — "Blocking", & 64 — "Gesture", transition yo'laklari — "Transition", retry yo'laklari — "Suspense", oxirgilari — "Idle".
4.2 Trekdagi hodisalar
Kanondagi o'lchov skripti (olchov/profil.mjs) Chrome trace'idan React yozgan hodisalarni yig'di (natijalar/22-profil.txt, katak bosilganda; faylda bir qatorda, bu yerda telefon uchun bo'lindi). Har qator — bitta trek: / dan oldin guruh, keyin trek nomi, ikki nuqtadan keyin shu trekdagi hodisalar:
Scheduler ⚛/Blocking: Blocking Track, Event: click, Update,
Render, Commit, Waiting, Remaining Effects, Waiting for Paint
Scheduler ⚛/Transition: Transition Track, Event: click, Action,
Prewarm, Suspended, Render, Commit, Waiting for Paint,
Remaining Effects, Update Blocked
Scheduler ⚛/Suspense: Suspense Track
Scheduler ⚛/Idle: Idle Track
/Components ⚛: VazifaRoyxati, VazifaQatori, OddiyQator, Qator,
BelgilanganMatn, AmalTugmasiBitta katak bosish — ikki trekda ish:
- Blocking:
Event: click→Update→Render→Commit→Waiting for Paint. Bu —useOptimisticning darhol ko'rinadigan yangilanishi (useOptimistic). - Transition:
Action(server so'rovi kutilmoqda),Prewarm(Suspense ichidagi oldindan render, Suspense),Render,Commit. Bu — tasdiq vastartTransitionqismi.
Bu bitta rasm 18-qismning birinchi o'n darsini birlashtiradi: concurrent rendering, Actions, Suspense — hammasi o'z trekida, millisekund aniqlikda.
Tekshirib ko'ring: Qidiruvga harf yozildi, Blocking trekida
Render2 ms, Transition trekida esa 250 ms. Foydalanuvchi qotishni sezadimi?
Javob
Odatda yo'q. Blocking — shoshilinch yangilanish (harf maydonga chiqdi) va u 2 ms. 250 ms lik transition renderi bo'laklarda ketadi va yangi harf kelsa to'xtaydi (Concurrent rendering). INP shoshilinch javobga qaraydi. Lekin Transition trekida bitta uzun bo'linmagan blok bo'lsa (bitta og'ir komponent), u ham bosishlarni ushlab turadi — shunda u ham davolanishi kerak.
5. Boshqa vositalar
| Vosita | Nima qiladi | Qachon |
|---|---|---|
| react-scan | sahifada qayta chizilgan komponentlarni ramka bilan, son va vaqt bilan ko'rsatadi | "nima ko'p chizilyapti?" — DevTools ochmasdan, tez |
| why-did-you-render | "oldini olish mumkin bo'lgan" renderlarni (props mazmunan o'sha, havola boshqa) konsolga yozadi | memo buzilishini ov qilish |
web-vitals onINP |
haqiqiy foydalanuvchilardagi INP | production monitoring (Core Web Vitals) |
| Event Timing API | har bosish va harfning to'liq kechikishi | avtomatik o'lchov skriptlari (kanon katak-tezligi.mjs) |
react-scan va why-did-you-render — uchinchi tomon kutubxonalar: ular React ichiga ulanadi, shuning uchun har React yangilanishida ularning qo'llab-quvvatlashini (CHANGELOG, peer) tekshiring (React 18 dan 19 ga darsidagi peer saboqlari). Ikkalasi faqat dev uchun — production bundle'ga kirmasin.
vazifalar da web-vitals 17-qismdan beri bor: olchov.ts alohida chunk bo'lib yuklanadi va INP, CLS, LCP ni yozadi.
6. Vazifalar qadami: profiling build va <Profiler> (holat 22)
6.1 Reja
Yangi branch: build/profil. Maqsad: production bilan bir xil, lekin <Profiler> va Performance Tracks ishlaydigan build — npm run build:profil. Oddiy build'ga hech qanday ta'sir yo'q. Diff: 8 fayl, +53 −6.
6.2 vite.config.ts: ikki joy
resolve: {
alias: {
// npm run build:profil (18/#22): react-dom'ning
// profiling build'i — <Profiler onRender> va Performance
// panelidagi React treklari production'da ham. Oddiy
// build'ga ta'sir qilmaydi
...(mode === "profil"
? { "react-dom/client": "react-dom/profiling" }
: {}), build: {
// profil build alohida papkaga — dist/ (deploy) bilan
// aralashmasin
outDir: mode === "profil" ? "dist-profil" : "dist", output: {
// profil build: funksiya nomlari saqlanadi —
// Performance panelidagi "Components ⚛" trekida "It, Nt"
// emas, "App, VazifaQatori" (18/#22; o'lchandi). Oddiy
// build'da — yo'q
keepNames: mode === "profil",Izohlar telefon uchun qayta bo'lindi, kod — aynan. Uch qaror bor.
- Alias —
vite --mode profil(Vite III: env va rejimlar) bo'lsa,import { createRoot } from "react-dom/client"aslidareact-dom/profilingdan oladi. Ilova kodi o'zgarmaydi. dist-profil/— alohida papka: profil build tasodifan deploy bo'lmasin..gitignore,.prettierignoreva ESLintglobalIgnoresga ham qo'shildi.keepNames— minifikatsiya funksiya nomlarini qisqartiradi. Kanon buni o'lchab topdi: usizComponents ⚛trekidaIt, Nt, Mt, jt— o'qib bo'lmaydi. Narxi: profil bundle 272 → 343 KB (faqat profil build'da).
package.json:
"build:profil": "tsc -b && vite build --mode profil",.env.profil — production bilan bir xil API manzili, izohda nima uchun ekani.
6.3 profil.ts va App.tsx
import type { ProfilerOnRenderCallback } from "react";
export const chizildi: ProfilerOnRenderCallback = (
id,
faza, // "mount" | "update" | "nested-update"
haqiqiy, // actualDuration: shu commit'da daraxtni chizish (ms)
asosiy, // baseDuration: memo'siz hammasini chizish taxmini (ms)
boshlandi, // startTime
) => {
performance.measure(`⚛ ${id} ${faza}`, {
start: boshlandi,
duration: haqiqiy,
detail: { haqiqiy, asosiy },
});
};onRender natijasini konsolga emas, User Timing ga yozadi: performance.measure (Performance API). Afzalligi ikki tomonlama. Chrome Performance panelida o'lchov "Timings" yo'lagida React treklari yonida ko'rinadi. Avtomatik skript esa performance.getEntriesByType("measure") bilan o'qiydi — console.log ni parse qilish shart emas. ProfilerOnRenderCallback — @types/react dagi tayyor tur (React + TS II).
App.tsx da — ro'yxat <Profiler> bilan o'raldi:
{/* Profiler (18/#22): ro'yxat qancha vaqt chizildi —
faqat dev va build:profil'da o'lchaydi (profil.ts) */}
<Profiler id="royxat" onRender={chizildi}>
<VazifaRoyxati
vazifalar={korinadigan}
sorov={sorov}
tahrirId={tahrirId}
/>
</Profiler>6.4 O'lchov
olchov/profil.mjs — profil build'da, Chrome headless (natijalar/22-profil.txt):
| 1 000 vazifa | 10 000 vazifa | |
|---|---|---|
| ochilish (mount): haqiqiy / asosiy | 21.8 / 9.6 ms | 163.4 / 52.7 ms |
| katak, 1-commit: haqiqiy / asosiy | 1.3 / 9.2 ms | 8.8 / 54.8 ms |
| katak, 2- va 3-commit: haqiqiy | 0.4 va 0.4 ms | 3.8 va 2.0 ms |
| qidiruv "v" (hamma qator): haqiqiy / asosiy | 31.2 / 28.1 ms | 285.4 / 242.7 ms |
- katak — haqiqiy (actual)8,8 ms
- katak — memo'siz taxmin (base)54,8 ms
- qidiruv "v" — haqiqiy285,4 ms
- qidiruv "v" — taxmin242,7 ms
Manba: O'lchandi: vazifalar holat 22, npm run build:profil (react-dom/profiling), olchov/profil.mjs, Chrome headless, 2026-10-13 (natijalar/22-profil.txt)
Jadvalni o'qishda bitta ogohlantirish: ochilishdagi juftlikni solishtirmang. asosiy — "qayta chizish" taxmini, ochilish esa birinchi yaratish (DOM elementlari ham yasaladi). Solishtirish faqat yangilanishlarda (katak, qidiruv) ma'noli.
Uchta xulosa:
- Katak: 8.8 ms o'rniga 54.8 ms bo'lardi.
asosiy—memosiz hammasini chizish taxmini. Haqiqiy ish 6 barobar kam — holat 20 dagimemo(VazifaQatori)ning hissasi, endi production build'da o'lchangan. memo darsidagi render soni (18 056 → 68) — o'sha natijaning boshqa o'lchovi. - Qidiruv "v": haqiqiy ≥ asosiy. Hamma qator haqiqatan o'zgaradi (har birida belgilangan matn) — tejaydigan narsa yo'q. Bu yerda
memoemas, boshqa vosita kerak: kamroq qator chizish. - Ochilish: 10 000 vazifada 163 ms — faqat ro'yxatning render qismi, 50 087 DOM elementi bilan. Bu ham "kamroq qator chizish" muammosi.
Ikkala oxirgi xulosa — bitta yechimga ishora: ekranda ko'rinmaydigan qatorlarni umuman chizmaslik. Bu Virtualizatsiya — keyingi dars.
6.5 Tekshiruvlar va commit
Build, test, lint, format:check, tip — toza (natijalar/tekshiruv-22.txt); oddiy build hajmi o'zgarmadi (<Profiler> production'da jim). Brauzer: 159/159.
build: npm run build:profil — react-dom/profiling, <Profiler> o'lchovi7. Ko'p uchraydigan xatolar
| Belgi | Sabab | Davosi |
|---|---|---|
onRender production'da chaqirilmaydi |
oddiy build'da profiling o'chirilgan | react-dom/profiling alias bilan alohida build |
| dev'da o'lchangan raqamlar qo'rqitadi | dev build sekinroq, StrictMode ikki marta | profil build yoki production'da o'lchang |
Components trekida It, Nt |
minifikatsiya nomlarni qisqartirgan | profil build'da keepNames |
| Profiler yozuvi tushunarsiz, o'nlab commit | bir yozuvda ko'p harakat | bitta harakat — bitta yozuv |
nested-update har commit'da |
layout effektda setState |
hosilaviy qiymat — render paytida |
| "eng sekin komponent" mayda, lekin ko'p | ranked faqat o'z vaqtini ko'rsatadi | flamegraph'da butun qismga qarang |
8. Mashqlar
Mashqlar kurs/mashqlar/18/22-profiler/ da. Har yechimni «Ishga tushir» bilan sinang.
1-mashq (oson): qaysi vosita?
- "Bitta bosishda qaysi komponent necha ms oldi?":
- "Haqiqiy foydalanuvchilarda INP qancha?":
- "Transition kutildimi yoki bosishni bloklayaptimi?":
- "Komponent nega chizildi?":
Yechim
React DevTools Profiler — commit va komponent vaqtlari. web-vitals (onINP) — production'dagi haqiqiy foydalanuvchilar. Performance Tracks — React ishini brauzerning boshqa ishi bilan bitta vaqt chizig'ida, ustuvorlik bo'yicha. "Why did this render?" — Profiler ichidagi sabab yozuvi.
2-mashq (o'rta): commit'larni sanash
OrderPanel ni <Profiler> bilan o'rang va onRender da har id uchun commit sonini hisoblang. «Hisobot» tugmasi bosilganda konsolga OrderPanel: N commit chiqsin (N — shu paytgacha). Ikki marta «+1», keyin «Hisobot» — kutilgan natija pastda.
import { useState } from "react";
function OrderPanel() {
const [count, setCount] = useState(0);
return (
<div>
<button onClick={() => setCount(count + 1)}>+1</button>
<p>Buyurtmalar: {count}</p>
</div>
);
}Konsolda (kutilgan):
OrderPanel: 3 commitYechim
import { Profiler, useState } from "react";
const commits = new Map();
function countCommit(id) {
commits.set(id, (commits.get(id) ?? 0) + 1);
}
function OrderPanel() {
const [count, setCount] = useState(0);
return (
<div>
<button onClick={() => setCount(count + 1)}>+1</button>
<p>Buyurtmalar: {count}</p>
</div>
);
}
function App() {
function report() {
for (const [id, n] of commits) console.log(`${id}: ${n} commit`);
}
return (
<div>
<Profiler id="OrderPanel" onRender={countCommit}>
<OrderPanel />
</Profiler>
<button onClick={report}>Hisobot</button>
</div>
);
}Konsolda:
OrderPanel: 3 commitUchta: birinchi chizish (mount) va ikki «+1» (update). «Hisobot» bosilishi state'ni o'zgartirmaydi — commit yo'q. Hisob Map da, komponentdan tashqarida. Uni state'da saqlash mumkin emas: onRender dagi har set… yangi commit chaqirib, cheksiz halqa bo'lardi.
3-mashq (qiyin): nested-update ni yo'qoting
«nested-update» bo'limidagi Price komponentini tuzating: birinchi chizishda bitta commit bo'lsin (Price mount), ekranda esa 35000 so'm.
Yechim
import { Profiler } from "react";
function onRender(id, phase) {
console.log(id, phase);
}
function Price({ value }) {
const label = `${value} so'm`; // ✅ render paytida hisoblanadi
return <p>{label}</p>;
}
function App() {
return (
<Profiler id="Price" onRender={onRender}>
<Price value={35000} />
</Profiler>
);
}Konsolda:
Price mountEkranda:
35000 so'mlabel — value dan hosil bo'ladigan qiymat. Uni state'da saqlash va effektda yangilash — ikki commit va bir lahzalik bo'sh <p> (layout effekt bo'lgani uchun ko'rinmaydi, lekin ish ikki barobar). Hisob arzon bo'lsa — shunchaki render paytida; qimmat bo'lsa — useMemo (memo, useMemo, useCallback).
4-mashq: vazifalar — o'z o'lchovingiz
build/profil branch'ida «Vazifalar qadami» dagi o'zgarishlarni kiriting va npm run build:profil qiling. dist-profil/ ni statik server bilan oching (masalan npx vite preview --outDir dist-profil), 1 000 vazifa bilan. Chrome DevTools → Performance → yozishni boshlang → bitta katakni bosing → to'xtating. Scheduler ⚛ va Components ⚛ treklarini toping. Konsolda: performance.getEntriesByType("measure").filter((m) => m.name.startsWith("⚛")) — detail dagi haqiqiy va asosiy ni yozing. Commit va PR.
Yechim
Raqamlar kompyuteringizga bog'liq, lekin nisbat kanondagidek bo'lishi kerak: katakda haqiqiy asosiy dan bir necha barobar kichik (kanonda 1 000 da 1.3 / 9.2 ms). Agar ular yaqin bo'lsa — memo(VazifaQatori) ishlamayapti (holat 20 ni tekshiring). Performance'da Blocking trekida Event: click, Transition trekida Action — server javobini kutish. Components ⚛ da nomlar o'qiladigan bo'lsa — keepNames ishladi. Commit xabari — «Tekshiruvlar va commit» bo'limida.
9. Real ishda
- Performance budjeti: jamoalar "bitta bosish — 50 ms dan kam render" kabi chegara qo'yadi va profil build bilan CI'da o'lchaydi.
- Bug hisobotlari: "sekin" degan hisobotga Performance yozuvi (
.jsontrace) ilova qilinadi — React treklari bilan u to'liq hikoya. - Production monitoring: Sentry, Datadog kabi xizmatlar INP va long task'larni yig'adi; profil build esa faqat tahlil uchun, foydalanuvchiga emas.
- Intervyu savollari: "React ilovasining sekin joyini qanday topasiz?", "
actualDurationvabaseDurationfarqi?", "Production'da React'ni qanday profil qilasiz?", "Flamegraph'dagi kulrang nima?".
Xulosa
- Davolashdan oldin o'lchang: render, commit, paint yoki boshqa skript — har biriga boshqa davo.
- DevTools Profiler: bitta harakat — bitta yozuv; commit ustunlari, flamegraph (kulrang — chizilmadi), ranked, "Why did this render?".
<Profiler id onRender>:phase(mount/update/nested-update),actualDuration(haqiqiy) vabaseDuration(memo'siz taxmin) — farqi tejalgan ish.- Performance Tracks (React 19.2):
Scheduler ⚛— Blocking/Gesture/Transition/Suspense/Idle (lanes guruhlari),Components ⚛— komponent vaqtlari. - Production'da
onRenderva treklar yo'q —react-dom/profilingalias, alohidadist-profil,keepNames. vazifalar10 000: katak — haqiqiy 8.8 ms, taxmin 54.8 ms (memohissasi); qidiruv "v" va ochilish — kamroq qator chizish kerak.
Keyingi dars: Uzun ro'yxatlar: virtualizatsiya — 10 000 qatordan faqat ekrandagi 15 tasini chizish: ochilish ~760 → ~170 ms.
Manbalar
- React:
<Profiler>— react.dev/reference/react/Profiler - React: "React Performance tracks" — react.dev/reference/dev-tools/react-performance-tracks
- React 19.2 e'loni (2025-10-01) — react.dev/blog/2025/10/01/react-19-2
- Chrome DevTools: Performance paneli — developer.chrome.com/docs/devtools/performance
react-dom19.3.0 manba kodi:setCurrentTrackFromLanes— npm paketi- Kanon:
sinov/18/QADAMLAR.md(#22),natijalar/22-profil.txt,olchov/profil.mjs,natijalar/tekshiruv-22.txt
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!