Mundarija (36)
- Bu darsda
- 1. Nega bu kerak?
- 2. O'lchash: nima va qanday
- 2.1 Ikki xil o'lchov
- 2.2 Build jadvalida JS hajmi yo'q
- 2.3 JS yo'li: 132.4 dan 149.6 gacha
- 3. JS ichida nima bor
- 3.1 next analyze
- 3.2 Kanon topgan eng katta bo'laklar (holat 37, gzip)
- 4. Client chegarasini kichik saqlash
- 4.1 Muammo
- 4.2 Yechim: o'z Link imiz
- 4.3 Qoida
- 5. Kechiktirib yuklash: next/dynamic
- 5.1 G'oya
- 5.2 Jonli: kod faqat kerak bo'lganda
- 6. Prefetch va <Activity>: tezlikning yashirin narxi
- 6.1 Prefetch
- 6.2 <Activity>: eski sahifa yashirin yashaydi
- 7. LCP va animatsiya: va'da bajarildi
- 7.1 Kanon o'lchovi
- 7.2 Biz o'lchadik: uch variant
- 7.3 SEO 92 — nega 100 emas
- 8. Qolgan vositalar
- 8.1 React Compiler
- 8.2 Maydon o'lchovi: useReportWebVitals
- 9. Portfolio qadami: holat 38 va commit
- 10. Ko'p uchraydigan xatolar
- 11. Mashqlar
- 1-mashq (oson): qaysi vosita?
- 2-mashq (o'rta): «Yana ko'rsatish» kechiktirib
- 3-mashq (qiyin): JS byudjeti
- 4-mashq: Portfolio qadami
- 12. Real ishda
- Xulosa
- Manbalar
Next.js performance: Lighthouse, brauzer yuklagan JS va client chegarasi
Qisqacha: Next.js ilovasining tezligi taxmin bilan emas, o'lchov bilan boshqariladi. Laboratoriyada — Lighthouse (mobil), haqiqiy foydalanuvchida —
useReportWebVitals. Brauzerga ketadigan JS'ning katta qismini React va Next'ning o'zi oladi (portfolioda ~132 KB gzip). Sizning qo'lingizdagi asosiy dastak — client chegarasini kichik saqlash. Og'ir ish serverda,"use client"esa faqat kerakli kichik komponentda. Kanonportfolioda ikki o'zgarish o'lchangan natija berdi: next-intl client qismini o'zLinkimiz bilan almashtirish (161.7 → 149.6 KB) va LCP'ni kechiktirgan kirish animatsiyasini olib tashlash (Performance 93–96 → 97–98).
Bu darsda
- Lighthouse natijasini o'qiysiz va LCP qaysi qismlardan iboratini bilasiz.
- Next 16.4 build jadvalida "First Load JS" yo'qligini va JS'ni boshqacha qanday o'lchashni bilasiz.
next analyzebilan og'ir modulni topasiz va client chegarasini toraytirib JS'ni kamaytirasiz.next/dynamic(Reactlazy), prefetch va<Activity>ning foydasi va narxini tushuntirasiz.- Kirish animatsiyasining LCP narxini o'lchov bilan ko'rasiz — va LCP'ni kechiktirmaydigan variantini.
Oldin bilishingiz kerak: Core Web Vitals: LCP, INP, CLS, Yuklanishni optimallashtirish, lazy va code splitting, <Activity>, Layout va template, next.config chuqur.
1. Nega bu kerak?
Next.js nima darsida narxni ko'rgandingiz: bo'sh Next sahifasi brauzerga 132.4 KB (gzip) JS yuboradi. v1 portfolio — faqat HTML, CSS va kichik asosiy.js. Har qo'shilgan client komponent, har kutubxona bu raqamni oshiradi.
Layout va template darsida esa va'da berdik: 200 ms lik kirish animatsiyasi LCP'ni kechiktirdi, va "LCP'ni kechiktirmaydigan variantini Performance darsida sinab ko'ramiz". Bu dars — o'sha.
Telefon va sekin internet — Aziz'ning o'quvchilari (va ish beruvchilari) aynan shunday ochadi. Lighthouse mobil profili shuni taqlid qiladi: o'rtacha telefon, sekin 4G.
O'xshatish: chamadon. Safarga hamma narsani olsangiz, chamadon og'ir — aeroportda kechikasiz. Tajribali sayohatchi avval tarozida o'lchaydi, keyin keraksizini chiqaradi. Lighthouse — tarozi, next analyze — chamadon ichini ko'rsatadigan rentgen.
2. O'lchash: nima va qanday
2.1 Ikki xil o'lchov
| Laboratoriya (lab) | Maydon (field) | |
|---|---|---|
| Vosita | Lighthouse, DevTools | useReportWebVitals, Speed Insights, CrUX |
| Qayerda | Sizning kompyuteringizda, taqlid | Haqiqiy foydalanuvchilar brauzerida |
| Afzalligi | Takrorlanadi, o'zgarishni solishtirish oson | Haqiqat |
| Kamchiligi | Taqlid — haqiqiy telefon emas | Ko'p tashrif kerak, kechikib keladi |
Core Web Vitals darsida uchtasini o'rgangansiz: LCP (eng katta element chizilishi), INP (bosishga javob), CLS (sakrash). Kanon laboratoriya o'lchovini qildi: Lighthouse 13.5.0, mobil, Chrome 155.
2.2 Build jadvalida JS hajmi yo'q
Next 15 gacha next build har sahifa yonida "First Load JS" ustunini chiqarardi. Next 16.0 da bu raqamlar olib tashlangan (CLI hujjatining versiya tarixi), 16.4 da ham yo'q — kanon buni build chiqishida ko'rdi. Holat 37 build jadvalidan parcha:
Route (app) Revalidate Expire
┌ ○ /_not-found
├ /[locale]
│ ├ ◐ /[locale]
│ ├ ○ /uz
│ └ ○ /en
├ /[locale]/blog 30d 1y
├ ƒ /api/qayta-yangila
└ ○ /sitemap.xml 30d 1yFaqat render turi (○, ◐, ƒ) va kesh muddati. Shuning uchun kanon JS'ni brauzerda o'lchadi: sahifani headless Chrome'da ochib, tarmoqdan kelgan JS fayllarni (gzip) qo'shib chiqdi. Bu raqam "foydalanuvchi aslida nimani yuklaydi" degan savolga eng halol javob.
2.3 JS yo'li: 132.4 dan 149.6 gacha
portfolio bosh sahifasining JS hajmi asosiy holatlarda (pastdagi raqam — holat, ya'ni dars raqami):
| holat | / |
|---|---|
| 2 | 132,4 |
| 6 | 137,4 |
| 8 | 143,4 |
| 23 | 145,6 |
| 30 | 146,5 |
| 34 | 161,7 |
| 38 | 149,6 |
Manba: IlmHamroh kanoni, sahifalar.mjs (Chrome 155, gzip tarmoq baytlari), 2026-10-21
Grafikda 7 ta nuqta; oraliq holatlar (04 — 135.4, 13 — 143.9 KB) tushirib qoldirildi, yo'nalish o'zgarmaydi. Chiziqqa qarang: deyarli tekis, bitta keskin sakrash — holat 34 (next-intl, +15.2 KB) va keyingi tushish — holat 38 (bu dars). 132.4 KB — Next va React'ning o'zi, uni olib tashlab bo'lmaydi. Qolgan 17 KB — butun portfolio: modal, filtr, tema, forma.
Tekshirib ko'ring: Blog posti sahifasi Markdown'ni HTML'ga aylantirish uchun
markedkutubxonasini (540 KBnode_modules) ishlatadi. U brauzer JS'iga qancha qo'shadi?
Javob
Nol. marked Server Component'da ishlaydi: Markdown build vaqtida serverda HTML'ga aylanadi, brauzerga faqat tayyor HTML boradi. Blog sahifasining JS'i (144.7 KB) eng kichiklardan. "Og'ir ishni serverda qiling" — Next hujjatining asosiy performance maslahati ham shu.
3. JS ichida nima bor
3.1 next analyze
Next 16.1 dan beri Turbopack uchun o'z bundle tahlilchisi bor (16.1 da next experimental-analyze nomi bilan qo'shilgan, 16.4 hujjatida — next analyze). Biz portfolio (holat 43 nusxasi) da ishga tushirdik:
npx next analyze --output✓ Running next.config.ts took 70ms
Analyzing a production build...
✓ Analyze completed in 2.8s. Results written to C:\Users\…\p\.next\diagnostics\analyze.
To explore the analyze results interactively, run `next analyze` without `--output`.--output siz npx next analyze brauzerda interaktiv xarita ochadi: har modul — to'rtburchak, maydoni — hajmi. Modulni bossangiz, uni kim import qilganini (import zanjiri) ko'rsatadi. --output esa natijani diskka yozadi (bizda 8.9 MB papka) — jamoadoshga yuborish yoki "oldin/keyin" solishtirish uchun. Kanon kuzatdi: natija ikkilik ma'lumot, matnli hisobot yo'q — tahlil UI orqali.
Webpack bilan ishlaydigan loyihalarda (eski) — @next/bundle-analyzer plagini; Next hujjati uni alohida bo'limda beradi.
3.2 Kanon topgan eng katta bo'laklar (holat 37, gzip)
| Bo'lak | Hajm | Kimniki |
|---|---|---|
| react-dom | 73.3 KB | React |
| Next runtime (ikki chunk) | 39.4 + 35.7 KB | Next.js router, RSC klienti |
| next-intl / use-intl | 14.3 KB | i18n kutubxonasi |
| modal | 5.9 KB | bizning RasmOynasi |
Birinchi ikkitasi — framework, ularni olib tashlab bo'lmaydi. Uchinchisi — next-intl — kanonni qiziqtirdi: NextIntlClientProvider ga messages={null} berilgan, ya'ni brauzerda tarjima umuman ishlatilmaydi. Lekin 14.3 KB baribir yuklanadi (IntlMessageFormat va boshqalar).
4. Client chegarasini kichik saqlash
4.1 Muammo
next-intl darsida portfolio da brauzerga kerak bo'lgan yagona i18n narsasi — havolalarga /en prefiksini qo'shish edi. Tarjima esa serverda (getTranslations). next-intl'ning client qismi buning uchun butun xabar formatlash dvigatelini olib keldi.
4.2 Yechim: o'z Link imiz
Kanon holat 38 da NextIntlClientProvider ni olib tashladi va src/i18n/navigation.tsx ni yozdi — next/link ustida yupqa o'ram:
"use client";
import NextLink from "next/link";
import { useParams } from "next/navigation";
import type { ComponentProps } from "react";
import { routing } from "./routing";
import { tilYoli } from "./yol";
function joriyTil(
params: Record<string, string | string[] | undefined>,
): string {
const t = params.locale;
return typeof t === "string" ? t : routing.defaultLocale;
}
/** href — tilsiz ichki yo'l; joriy til prefiksi o'zi qo'shiladi */
export function Link({
href,
...props
}: Omit<ComponentProps<typeof NextLink>, "href"> & { href: string }) {
const til = joriyTil(useParams());
return <NextLink href={tilYoli(til, href)} {...props} />;
}Faylda yana usePathname o'rami bor (/en/blog → /blog); bu yerda qisqartirildi. Kanon izohi: "next-intl client qismi brauzerga 14.3 KB gzip qo'shardi, bizga esa faqat /en prefiksi kerak".
Natija (kanon o'lchovi): bosh sahifa JS 161.7 → 149.6 KB gzip (−12.1), xom 524.2 → 485.1 KB. Regressiya: til almashtirgich, lang atributi, inglizcha forma xatolari — o'zgarmadi.
4.3 Qoida
Client chegarasi — daraxtdagi "use client" qo'yilgan nuqta: undan pastdagi hamma import brauzerga ketadi (Client Components). Uch amaliy savol:
| Savol | Agar "ha" bo'lsa |
|---|---|
| Bu komponentga bosish, state, effekt kerakmi? | Client — lekin faqat shu kichik qism |
| Kutubxona ma'lumotni UI'ga aylantiradimi (Markdown, grafik, kod rang berish)? | Serverda qiling |
| Kutubxona'ning client qismidan nimadir 10% ishlatilyaptimi? | O'z kichik o'ramingizni yozing (o'lchab!) |
Uchinchisida "o'lchab" so'zi muhim. O'z kodingiz — xizmat ko'rsatish narxi: next-intl yangilansa, o'ram o'zgarmaydi; createNavigation ning ba'zi imkoniyatlari (masalan typed pathnames) yo'q. Kanon −12 KB uchun shu narxni qabul qildi va sababni kodga yozdi.
5. Kechiktirib yuklash: next/dynamic
5.1 G'oya
Ba'zi komponent sahifada bor, lekin darhol kerak emas: tugma bosilgandagina ochiladigan grafik, xarita, muharrir. Uning kodini sahifa bilan birga yuklash — isrof. lazy darsida React'ning lazy + Suspense ini ko'rgansiz. Next'da uning o'rami — next/dynamic:
"use client";
import dynamic from "next/dynamic";
const Grafik = dynamic(() => import("./Grafik"), {
loading: () => <p>Yuklanmoqda…</p>,
});ssr: false qo'shilsa, komponent serverda umuman chizilmaydi (faqat brauzer API'siga muhtoj kutubxonalar uchun). Bu variant faqat client komponent ichida ishlaydi.
5.2 Jonli: kod faqat kerak bo'lganda
Natija oynasida next/dynamic yo'q, lekin u ichida aynan React lazy ishlaydi. «Ishga tushir» ni bosing — konsolga qarang:
import { lazy, Suspense, useState } from "react";
function Chart() {
return <p>Grafik: 3 ta ustun</p>;
}
const LazyChart = lazy(() => {
console.log("grafik kodi yuklanmoqda");
return Promise.resolve({ default: Chart });
});
export default function App() {
const [show, setShow] = useState(false);
return (
<section>
<h1>Loyiha statistikasi</h1>
<button onClick={() => setShow(true)}>
Grafikni ko'rsatish
</button>
{show && (
<Suspense fallback={<p>Yuklanmoqda…</p>}>
<LazyChart />
</Suspense>
)}
</section>
);
}Konsolda:
grafik kodi yuklanmoqdaEkranda:
Loyiha statistikasi
Grafikni ko'rsatish
Grafik: 3 ta ustun"grafik kodi yuklanmoqda" — faqat tugma bosilgach. Tugmani bosmagan foydalanuvchi grafik kodini umuman yuklamaydi. Haqiqiy loyihada import("./Grafik") alohida JS fayl (chunk) bo'lib, tarmoqdan keladi; bu yerda Promise.resolve uni taqlid qiladi.
portfolio da next/dynamic yo'q — og'ir client komponent yo'q (eng kattasi modal, 5.9 KB). Kechiktirish ham bepul emas: tugma bosilganda kutish paydo bo'ladi. U 30–50 KB dan katta, darhol ko'rinmaydigan narsalar uchun.
6. Prefetch va <Activity>: tezlikning yashirin narxi
6.1 Prefetch
<Link> ekranda ko'ringan zahoti Next uning sahifasini oldindan yuklaydi (prefetch) — bossangiz, o'tish bir zumda. portfolio da partialPrefetching: true (Navigatsiya): sahifaning statik qismi oldindan olinadi. Kanon o'lchadi — sahifa ochilganda prefetch so'rovlari:
/: RSC prefetch 13 ta, 59.0 KB (xom)
/loyihalar: RSC prefetch 22 ta, 60.7 KB (xom)
/blog: RSC prefetch 14 ta, 56.2 KB (xom)Har ko'rinadigan havola — bitta RSC so'rovi. 22 ta so'rov, ~60 KB — foydalanuvchi hech qayerni bosmasa ham. Mobil internet paketida bu sezilarli. Kanon o'zgartirmadi: sayt kichik, navigatsiya tezligi muhimroq. Lekin ro'yxat 200 ta havola bo'lsa (masalan katta katalog), <Link prefetch={false}> — bosilganda yuklash — to'g'ri tanlov bo'ladi.
6.2 <Activity>: eski sahifa yashirin yashaydi
Activity darsida aytgandik: framework'lar <Activity> dan navigatsiyada foydalanadi. Next 16 hujjati aniq yozadi: Cache Components yoqilganda Next sahifadan chiqqanda uni o'chirmaydi, <Activity> bilan yashiradi (display: none) — state va DOM saqlanadi. Ko'pi bilan 3 ta marshrut; undan eskisi o'chiriladi. Natija oynasida mexanizmni ko'ring — «+1» ni ikki marta bosib, Blog'ga o'ting va qaytib keling:
import { Activity, useState } from "react";
function HomePage() {
const [count, setCount] = useState(0);
return (
<div>
<p>Bosh sahifa: {count}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
);
}
export default function App() {
const [page, setPage] = useState("/");
return (
<>
<nav>
<button onClick={() => setPage("/")}>Bosh sahifa</button>{" "}
<button onClick={() => setPage("/blog")}>Blog</button>
</nav>
<Activity mode={page === "/" ? "visible" : "hidden"}>
<HomePage />
</Activity>
{page === "/blog" && <p>Blog sahifasi</p>}
</>
);
}Ekranda:
Bosh sahifa Blog
Bosh sahifa: 2
+1Qaytganda hisob 2 — sahifa o'chirilmagan, yashiringan edi. Foydasi: orqaga qaytish bir zumda, yozilgan forma, scroll joyida. Narxi: xotira. Uchta sahifa DOM'i va state'i bir vaqtda yashaydi. Shuning uchun Next chegarani 3 ta bilan qo'ygan. Ochiq qolib ketgan menyular kabi "vaqtinchalik" holatni esa effekt tozalashida yopish kerak (Next hujjatidagi "Preserving UI state" qo'llanmasi).
7. LCP va animatsiya: va'da bajarildi
7.1 Kanon o'lchovi
Holat 37 da hamma sahifada template.tsx dagi 200 ms kirish animatsiyasi bor edi (opacity: 0 + translate). Lighthouse (mobil), 5 sahifa:
| Performance | LCP | TBT | |
|---|---|---|---|
| holat 37 (animatsiya bilan) | 93–96 | 2.7–3.2 s | 40–80 ms |
| holat 38 (animatsiyasiz, o'z Link) | 97–98 | 2.4–2.6 s | 40–90 ms |
Bosh sahifaning LCP elementi — kirish paragrafi (main > p). Lighthouse LCP'ni qismlarga ajratdi: "Element render delay" (elementni chizish kechikishi) 345 ms — paragraf opacity: 0 dan boshlanadi, brauzer uchun shaffof matn "hali chizilmagan".
7.2 Biz o'lchadik: uch variant
Layout va template darsida taxmin aytgandik: animatsiyani faqat translate bilan qilsa (opacity siz), LCP kechikmasligi kerak. Tekshirdik. portfolio holat 43 nusxasiga template.tsx ni qaytardik va uch variantni bir xil sharoitda o'lchadik — har biri 3 marta, Lighthouse 13.5.0 mobil, Chrome 155:
yoq #1 /: perf 98 | LCP 2.4 s, FCP 0.8 s, TBT 50 ms, CLS 0 | timeToFirstByte 21 ms, elementRenderDelay 111 ms
yoq #2 /: perf 98 | LCP 2.4 s, FCP 0.8 s, TBT 40 ms, CLS 0 | timeToFirstByte 6 ms, elementRenderDelay 86 ms
yoq #3 /: perf 98 | LCP 2.4 s, FCP 0.8 s, TBT 40 ms, CLS 0 | timeToFirstByte 15 ms, elementRenderDelay 88 ms
opacity #1 /: perf 97 | LCP 2.6 s, FCP 0.8 s, TBT 40 ms, CLS 0 | timeToFirstByte 17 ms, elementRenderDelay 317 ms
opacity #2 /: perf 93 | LCP 3.2 s, FCP 0.8 s, TBT 100 ms, CLS 0 | timeToFirstByte 7 ms, elementRenderDelay 275 ms
opacity #3 /: perf 94 | LCP 3.0 s, FCP 0.8 s, TBT 90 ms, CLS 0 | timeToFirstByte 8 ms, elementRenderDelay 319 ms
translate #1 /: perf 98 | LCP 2.4 s, FCP 0.8 s, TBT 50 ms, CLS 0 | timeToFirstByte 17 ms, elementRenderDelay 150 ms
translate #2 /: perf 98 | LCP 2.4 s, FCP 0.8 s, TBT 40 ms, CLS 0 | timeToFirstByte 6 ms, elementRenderDelay 60 ms
translate #3 /: perf 98 | LCP 2.4 s, FCP 0.8 s, TBT 50 ms, CLS 0 | timeToFirstByte 8 ms, elementRenderDelay 86 msMediana (o'rtadagi qiymat) bilan:
- animatsiyasizperf 98, LCP 2.4 s88 ms
- opacity + translateperf 94, LCP 3.0 s317 ms
- faqat translateperf 98, LCP 2.4 s86 ms
Manba: IlmHamroh, biz ishga tushirdik: portfolio holat 43 + template, Lighthouse 13.5.0 mobil, Chrome 155, 2026-10-21
Taxmin tasdiqlandi. opacity siz animatsiya LCP'ga ta'sir qilmadi — natija animatsiyasiz variant bilan bir xil. Sababi: LCP "element ekranda ko'rindi" paytini o'lchaydi. Siljiyotgan, lekin ko'rinadigan matn — ko'rindi; shaffof matn — yo'q.
Kanon baribir animatsiyani olib tashladi (holat 38) — sodda yo'l. Siz portfolio ingizda translate variantni qoldirsangiz ham, endi narxi nol ekanini bilasiz. Asosiysi — o'lchov taxminni tasdiqladi yoki rad etdi, bahs emas.
E'tibor bering: bitta o'lchov aldaydi. opacity #1 da Performance 97 — yaxshi ko'rinadi. Uchta o'lchov 93–97 oralig'ini berdi. Lighthouse natijasi har safar biroz o'zgaradi — xulosani bir nechta o'lchovdan chiqaring.
7.3 SEO 92 — nega 100 emas
Hamma o'lchovda SEO 92 edi, sababi bitta: canonical havola example.com ga ishora qiladi, Lighthouse esa localhost ni o'lchaydi. Kanon SAYT_URL=http://localhost:3127 bilan build qildi — SEO 100. Bu Env o'zgaruvchilar darsidagi "build vaqtida yoziladi" faktining yana bir ko'rinishi.
8. Qolgan vositalar
8.1 React Compiler
reactCompiler: true (next.config chuqur) — komponentlarni avtomatik memo qiladi (React Compiler). U qayta render muammosini yechadi — INP va interaktivlik. portfolio da bunday muammo o'lchanmagan: client komponentlar kichik, TBT 40–90 ms. Kanonga kirmadi. Qoida o'sha: avval DevTools Profiler'da sekin render'ni toping, keyin yoqing.
8.2 Maydon o'lchovi: useReportWebVitals
Haqiqiy foydalanuvchilarda Web Vitals'ni yig'ish uchun Next hook beradi:
"use client";
import { useReportWebVitals } from "next/web-vitals";
export function WebVitals() {
useReportWebVitals((metric) => {
// metric.name: "LCP" | "INP" | "CLS" | "FCP" | "TTFB"
navigator.sendBeacon("/api/vitals", JSON.stringify(metric));
});
return null;
}Komponent root layout'ga qo'yiladi. Callback har safar yangi funksiya bo'lmasligi kerak. Hujjat ogohlantiradi: aks holda bir o'lchov ikki marta yuboriladi. Core Web Vitals darsida web-vitals kutubxonasi bilan qilgan ishning Next'dagi o'rni shu. portfolio da yo'q: o'lchovni yig'adigan joy (backend) hali yo'q. Vercel'ning Speed Insights xizmati xuddi shuni tayyor qiladi — Vercel hisobi kerak, biz sinamadik.
9. Portfolio qadami: holat 38 va commit
| O'zgarish | Natija |
|---|---|
template.tsx va sahifa-kirish animatsiyasi olib tashlandi |
LCP 2.7–3.2 → 2.4–2.6 s |
src/i18n/navigation.tsx — o'z Link va usePathname; NextIntlClientProvider olib tashlandi |
JS 161.7 → 149.6 KB |
Kanon tekshiruvi: lint, tip, format — 0; axe 0, hydration 0; regressiya (filtr, modal, tema, forma, i18n, CSP) — o'tdi. Holat 38 jadvali:
| Sahifa | JS gzip | Lighthouse Perf |
|---|---|---|
/, /loyihalar |
149.6 KB | 98 |
/loyihalar/vazifalar |
155.3 KB | 97 |
/blog/portfolio-v2 |
144.7 KB | 98 |
/en/aloqa |
144.1 KB | 98 |
git add -A
git commitCommit (kanon): Perf: next-intl client qismi o'z Link/usePathname bilan almashtirildi (−12 KB), template animatsiyasi olib tashlandi (LCP).
10. Ko'p uchraydigan xatolar
| Belgi | Sabab | Davosi |
|---|---|---|
| Build jadvalida "First Load JS" yo'q | Next 16.4 uni olib tashlagan | Brauzerda o'lchang yoki next analyze |
| Bitta Lighthouse o'lchovidan xulosa | Natija har safar o'zgaradi | 3+ o'lchov, mediana |
| LCP kechikdi, JS kichik | opacity: 0 dan boshlanuvchi animatsiya LCP elementida |
opacity siz yoki LCP bo'lmagan elementga |
| Kutubxona brauzer JS'ini oshirdi, lekin faqat ma'lumotni o'zgartiradi | U client komponentda | Server Component'ga ko'chiring |
| Sahifa ochilganda o'nlab RSC so'rovi | Prefetch — har ko'rinadigan <Link> |
Ko'p havolali ro'yxatda prefetch={false} |
| Qaytganda menyu ochiq qolgan | <Activity> state'ni saqlagan |
Vaqtinchalik holatni effekt tozalashida yoping |
useReportWebVitals ikki marta yuboradi |
Callback har render'da yangi | Funksiyani komponentdan tashqarida e'lon qiling |
11. Mashqlar
Mashqlar kurs/mashqlar/23/38-performance/ da. Jonli yechimlarni «Ishga tushir» bilan sinang.
1-mashq (oson): qaysi vosita?
- Laboratoriyada Performance, LCP, TBT o'lchaydigan vosita —
- Next 16.1+ dagi Turbopack bundle tahlilchisi buyrug'i —
next - Komponent kodini kerak bo'lganda yuklaydigan Next API —
next/ - Havolani oldindan yuklamaslik —
<Link prefetch={}> - Next eski sahifalarni yashirib saqlaydigan React komponenti —
Yechim
- Lighthouse — mobil profil, taqlid qilingan sekin telefon.
- analyze —
--outputbilan diskka yozadi. - dynamic — ichida React
lazy+Suspense. - false — havola bosilgandagina yuklanadi.
- Activity — ko'pi bilan 3 ta marshrut.
2-mashq (o'rta): «Yana ko'rsatish» kechiktirib
«Kod faqat kerak bo'lganda» blokidagi naqsh bilan Comments komponentini kechiktirib yuklang. Sahifada post sarlavhasi va «Izohlarni ochish» tugmasi bor. Bosilganda Suspense fallback'i «Izohlar yuklanmoqda…», keyin ikki izoh chiqsin. Yuklash 200 ms davom etsin (setTimeout bilan Promise). Konsolga yuklash boshlanganini yozing va oraliq holatni ekran(…) bilan tekshiring.
Yechim
import { lazy, Suspense, useState } from "react";
function Comments() {
return (
<ul>
<li>Malika: Zo'r maqola!</li>
<li>Bobur: Kodini GitHub'ga qo'ying</li>
</ul>
);
}
const LazyComments = lazy(() => {
console.log("izohlar kodi yuklanmoqda");
return new Promise<{ default: typeof Comments }>((resolve) =>
setTimeout(() => resolve({ default: Comments }), 200),
);
});
export default function App() {
const [open, setOpen] = useState(false);
return (
<article>
<h1>Portfolio v2: Next.js'ga ko'chish</h1>
<button onClick={() => setOpen(true)}>Izohlarni ochish</button>
{open && (
<Suspense fallback={<p>Izohlar yuklanmoqda…</p>}>
<LazyComments />
</Suspense>
)}
</article>
);
}Konsolda:
izohlar kodi yuklanmoqdaEkranda:
Portfolio v2: Next.js'ga ko'chish
Izohlarni ochish
Malika: Zo'r maqola!
Bobur: Kodini GitHub'ga qo'yingekran("Izohlar yuklanmoqda…") qadami oraliq holatni tasdiqlaydi: 200 ms davomida fallback ko'rindi. Next'da dynamic(() => import("./Comments"), { loading: … }) aynan shu xulqni beradi, faqat fallback loading parametrida yoziladi.
3-mashq (qiyin): JS byudjeti
Performance budget (tezlik byudjeti) — "bu sahifa X KB dan oshmasin" degan qoida. Funksiya yozing: checkBudget(pages, budgetKb) — har sahifa uchun "/yo'l: 149.6 KB — ok" yoki "/yo'l: 161.7 KB — +11.7 KB oshdi" qaytarsin; oxirida oshgan sahifalar sonini chiqaring. Kanon raqamlari bilan sinang: holat 34 (/ 161.7, /blog/portfolio-v2 156.8) va holat 38 (/ 149.6, /blog/portfolio-v2 144.7), byudjet 155 KB. Sonlarni toFixed(1) bilan yozing.
Yechim
function checkBudget(pages, budgetKb) {
const lines = pages.map(({ path, kb }) => {
const over = kb - budgetKb;
const size = `${path}: ${kb.toFixed(1)} KB`;
return over > 0
? `${size} — +${over.toFixed(1)} KB oshdi`
: `${size} — ok`;
});
const failed = pages.filter(({ kb }) => kb > budgetKb).length;
return { lines, failed };
}
const runs = {
"holat 34": [
{ path: "/", kb: 161.7 },
{ path: "/blog/portfolio-v2", kb: 156.8 },
],
"holat 38": [
{ path: "/", kb: 149.6 },
{ path: "/blog/portfolio-v2", kb: 144.7 },
],
};
for (const [name, pages] of Object.entries(runs)) {
const { lines, failed } = checkBudget(pages, 155);
console.log(`${name}: ${failed} ta sahifa oshdi`);
for (const line of lines) console.log(` ${line}`);
}Konsolda:
holat 34: 2 ta sahifa oshdi
/: 161.7 KB — +6.7 KB oshdi
/blog/portfolio-v2: 156.8 KB — +1.8 KB oshdi
holat 38: 0 ta sahifa oshdi
/: 149.6 KB — ok
/blog/portfolio-v2: 144.7 KB — okBunday tekshiruv CI'da har PR'da ishlaydi: kimdir og'ir kutubxona qo'shsa, PR qizil bo'ladi. Holat 34 da next-intl aynan shunday "qizil" bo'lardi — muammo kanon o'lchovida emas, byudjet qoidasida ham ko'rinardi. toFixed — son metodlari.
4-mashq: Portfolio qadami
O'z portfolio ingizni npm run build && npm run start qiling va Chrome DevTools → Lighthouse (Mobile, Performance) bilan bosh sahifani 3 marta o'lchang. LCP elementi qaysi? "LCP breakdown" da "Element render delay" qancha? Keyin kanon qadamini qiling: template.tsx animatsiyasini olib tashlang (yoki opacity ni olib tashlab, faqat translate qoldiring) va NextIntlClientProvider o'rniga o'z Link ingizni yozing. Qayta 3 marta o'lchang, farqni yozib qo'ying, commit qiling.
Yechim
Kutilgan yo'nalish (kanon raqamlari, sizniki biroz farq qiladi): Performance 93–96 → 97–98, LCP 2.7–3.2 → 2.4–2.6 s, render delay ~300 ms → ~90 ms. JS — DevTools → Network → "JS" filtri, "transferred" ustuni yig'indisi: ~161 → ~150 KB. Lighthouse'ni yashirin (inkognito) oynada ishga tushiring — brauzer kengaytmalari natijani buzadi. Natijalarni commit xabariga yoki README ga yozing: keyingi o'zgarishda solishtirish uchun.
12. Real ishda
- Performance — mahsulot ko'rsatkichi. Do'konlarda sekin sahifa sotuvni kamaytiradi; Google qidiruvi Core Web Vitals'ni hisobga oladi. Katta jamoalarda JS byudjeti CI'da tekshiriladi.
- "Use client" auditi — Next loyihasini tezlashtirishning birinchi qadami: qaysi komponent keraksiz client bo'lgan, qaysi kutubxona brauzerga tushib qolgan.
next analyzeaynan shu ish uchun. - Intervyu savollari: "LCP qanday qismlardan iborat?", "Next ilovasida JS'ni qanday kamaytirasiz?", "Prefetch'ning narxi nima?", "Lab va field ma'lumot farqi?".
- O'lchov madaniyati — "bu tezroq" degan gapga "qancha va necha o'lchovda?" deb so'rash — tajribali muhandisning belgisi. Bu darsdagi uch variantli tajriba shu madaniyatning kichik namunasi.
Xulosa
- Tezlik o'lchanadi: Lighthouse (lab, 3+ o'lchov) va
useReportWebVitals(field); Next 16.4 build jadvalida JS hajmi yo'q. portfolioJS'ining ~132 KB i — React va Next; sizning dastagingiz — client chegarasini kichik saqlash va og'ir ishni serverda qilish.- next-intl client qismi o'rniga o'z
Link— 161.7 → 149.6 KB;next analyzeog'ir modulni topadi. next/dynamic(lazy) — darhol kerak bo'lmagan katta komponentlar uchun; prefetch va<Activity>tezlik beradi, lekin trafik va xotira narxi bor.opacity: 0dan boshlanadigan animatsiya LCP'ni ~230 ms kechiktiradi; faqattranslate— kechiktirmaydi (biz o'lchadik).
Keyingi dars: Runtime'lar: Node va Edge — Next server kodi qayerda ishlaydi, nega Next 16 hujjati Edge'ni "eskirgan" deydi va serverless'da bazaga ulanish muammosi.
Manbalar
- Next.js hujjati — Package Bundling (
next analyze,@next/bundle-analyzer): https://nextjs.org/docs/app/guides/package-bundling (16.4.0 bilan kelgan nusxa, 2026-10-21 da o'qildi) - Next.js hujjati — Lazy Loading (
next/dynamic),useReportWebVitals, Prefetching, Preserving UI state (Activity, 3 ta marshrut): https://nextjs.org/docs/app/guides - web.dev — Optimize LCP (LCP qismlari): https://web.dev/articles/optimize-lcp
- Kanon:
portfoliov2, holat 37/38 Lighthouse va JS o'lchovlari, prefetch o'lchovi;next analyze --outputva animatsiyaning uch varianti — biz ishga tushirdik (next 16.4.0, Lighthouse 13.5.0 mobil, Chrome 155).
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!