Mundarija (33)
- Bu darsda
- 1. Nega bu kerak?
- 2. Loyiha rejasi
- 2.1 Nima qurildi
- 2.2 Talablar (boshidanoq)
- 3. Arxitektura
- 3.1 Qatlamlar
- 3.2 Papkalar
- 4. Texnologiya tanlovlari va narxi
- 4.1 Kirganlar
- 4.2 Kirmaganlar — o'lchov bilan
- 4.3 JS'ning yo'li
- 5. Bosqichma-bosqich qurish
- 5.1 20 commit
- 5.2 14 ta haqiqiy topilma
- 6. Jonli: loyihaning yuragi — aloqa formasi
- 7. Sifat: yakuniy tekshiruv
- 7.1 Raqamlar (holat 43)
- 7.2 Lighthouse (mobil, 7 sahifa)
- 7.3 Ochiq qolganlar (halol)
- 8. README va AGENTS.md
- 8.1 README
- 8.2 AGENTS.md
- 8.3 Commit
- 9. Ko'p uchraydigan xatolar
- 10. Mashqlar
- 1-mashq (oson): qatlamlar
- 2-mashq (o'rta): forma email bilan
- 3-mashq (qiyin): tanlov hisoblagichi
- 4-mashq: Portfolio qadami — yakun
- 11. Real ishda
- Xulosa
- Manbalar
Yakuniy Next.js loyiha: portfolio v2 — arxitektura, tanlovlar va natija
Qisqacha:
portfoliov2 — 23-qismning hamma darsi bitta real loyihada: Server Components, Server Actions, Route Handler,proxy.ts, Cache Components, next-intl, SEO, CSP, testlar. 20 bosqich (commit), 63 ta oldindan tayyorlangan sahifa, faqat bitta dinamik API manzili. Yakuniy natija: Lighthouse mobil 97–98 / 100 / 100, axe 0, hydration ogohlantirishi 0, Vitest 10, Playwright 15, brauzer JS 144–155 KB gzip. Har texnologiya o'lchab tanlangan, kirmaganlari ham sababi bilan yozilgan. Oxirgi qadam — README vaAGENTS.md: loyihani boshqa odam (yoki AI agent) to'g'ri davom ettira olishi uchun.
Bu darsda
portfoliov2 ning arxitektura qatlamlarini chizib, har faylning o'rnini tushuntira olasiz.- Har texnologiya tanlovini (kirgan va kirmagan) narxi va sababi bilan himoya qilasiz.
- 20 bosqichli qurilish yo'lini va har bosqichda nima tekshirilganini ko'rasiz.
- Yakuniy sifat ko'rsatkichlarini o'qiysiz va 14 ta haqiqiy topilmadan saboq olasiz.
- README va
AGENTS.mdyozasiz va loyihani portfolio'ga tayyorlaysiz.
Oldin bilishingiz kerak: 23-qismning hamma darslari, ayniqsa Next.js nima, Server va Client kompozitsiyasi, Next.js performance, Next.js ilovani test qilish.
1. Nega bu kerak?
Kursning 04–09-qismlarida Aziz birinchi saytini qurdi: besh sahifa HTML, CSS va kichik asosiy.js. U GitHub Pages'da turibdi. 23-qism davomida o'sha saytni Next.js'da qaytadan qurdik — dizayn va mazmun o'sha, lekin ichi butunlay boshqa.
Yakuniy loyiha darsi yangi texnologiya o'rgatmaydi. U boshqa savolga javob beradi: "bularning hammasi birga qanday ishlaydi va nima uchun aynan shunday?". Ish beruvchi portfolio'ga qaraganda ham shuni so'raydi: "Nega Next? Nega Tailwind emas? Lighthouse necha? Testlar bormi?".
O'xshatish: uy qurib bo'lindi. Endi uning pasporti kerak — chizmalar, qaysi material nega tanlangani, sinov natijalari. Pasportsiz uy ham turadi, lekin uni sotish, ta'mirlash yoki kengaytirish qiyin.
2. Loyiha rejasi
2.1 Nima qurildi
| Sahifa | Nima bor | Render |
|---|---|---|
/ bosh sahifa |
kirish, so'nggi loyihalar, JSON-LD | ○ |
/loyihalar, /loyihalar/[slug] |
teg filtri (URL'da), case study, rasm modal'da | ○ (+◐ qobiq) |
/blog, /blog/[slug] |
Markdown postlar, ulashish tugmasi, RSS | ○, 30 kun kesh |
/haqimda |
GitHub profili (kalitsiz API, zaxira bilan) | ○, 1 soat kesh |
/aloqa |
Server Action forma, JS'siz ham ishlaydi | ○ |
/en/... |
hamma sahifaning inglizcha nusxasi | ○ |
/api/qayta-yangila |
sirli kesh tozalash | ƒ |
2.2 Talablar (boshidanoq)
Kanon loyihani boshlashdan oldin talablarni yozdi va har bosqichda ularni tekshirdi:
- JS'siz ishlaydi: matn, havolalar, forma — v1 dagi progressive enhancement saqlanadi.
- Ochiq va tez: sahifalar statik, Lighthouse mobil 95+.
- Hamma uchun: axe 0 buzilish, klaviatura, ekran o'quvchi.
- Ikki til: uz (prefikssiz) va
/en. - Halol: tashqi hisob, kalit, pullik xizmat yo'q — hammasi lokal o'lchanadi.
3. Arxitektura
3.1 Qatlamlar
flowchart TB
R["so'rov"] --> PX["proxy.ts<br/>noma'lum slug → 404, til"]
PX --> APP["app/[locale]/…<br/>sahifa va layout'lar"]
APP --> SC["Server Components"]
APP --> CC["client orollar<br/>filtr, tema, forma"]
SC --> DAL["malumot/dal.ts<br/>server-only, cache()"]
CC -->|"Server Action"| ACT["aloqa/_amal"]
DAL --> SRC["Markdown fayllar,<br/>GitHub API, env.ts"]
ACT --> LOG["log (instrumentation)"]Yuqoridan pastga — so'rovning yo'li. Uch narsaga qarang. Birinchisi: ma'lumot faqat bitta joydan — DAL orqali olinadi (Data Access Layer); sahifalar fayl yoki API bilan to'g'ridan gaplashmaydi. Ikkinchisi: client qismlar — kichik orollar; ular serverga faqat Server Action orqali murojaat qiladi. Uchinchisi: env faqat env.ts da (Env).
3.2 Papkalar
README'dagi tuzilma (kanon):
src/app/[locale]/ root layout (til URL'da), not-found, error
src/app/[locale]/(sayt)/ sahifalar: bosh, haqimda, loyihalar, blog, aloqa
src/app/ sitemap, robots, manifest, OG, rss, api, global-error
src/blog/*.md blog postlari
src/malumot/ ma'lumot, DAL, GitHub, tezlik cheklovi
src/i18n/ messages/ next-intl (serverda)
src/proxy.ts noma'lum slug → 404, til yo'naltirish
tekshiruv/ e2e/ Vitest va Playwright testlariKanondagi qatorlar telefonga sig'ishi uchun qisqartirildi. Qoidalar: (sayt) — route group (Route groups), _komponentlar va _amal — private papkalar (marshrut emas), har bo'lim o'z komponentlarini yonida saqlaydi.
4. Texnologiya tanlovlari va narxi
4.1 Kirganlar
| Paket | Versiya | Nega |
|---|---|---|
| next, react | 16.4.0, 19.3.0 | Asos |
| next-intl | 4.14.9 | Tarjima serverda; client qismi o'rniga o'z Link (−12 KB) |
| zod | 4.6.7 | Forma va env tekshiruvi — bitta sxema ikki joyda |
| marked | 18.1.1 | Markdown → HTML serverda, brauzerga 0 KB |
| server-only | 0.0.1 | Sir va server modullari himoyasi |
Hammasi --save-exact, va 7 kundan eski versiyalar (yangi versiyani darhol olmaslik — ta'minot zanjiri xavfsizligi, 16-qism).
4.2 Kirmaganlar — o'lchov bilan
| Nima | O'lchov | Nega kirmadi |
|---|---|---|
| Tailwind | node_modules +18 MB |
v1 dizayni CSS tokenlarda tayyor (Stil va tema) |
| @next/mdx | 9.8 MB, 104 paket | marked — 540 KB, postlar oddiy Markdown |
| gray-matter | oxirgi reliz 2021 | Faol emas; frontmatter o'zimiz o'qiymiz |
| TanStack Query | — | Client'da server holati yo'q (TanStack Query) |
useOptimistic |
— | JS'siz formani buzadi |
| next-themes | — | useSyncExternalStore + kichik skript yetdi |
| NextIntlClientProvider | +14.3 KB | Client'da tarjima kerak emas |
| template animatsiyasi | LCP +0.5 s | Performance o'lchovi |
| nonce CSP, SRI, Trusted Types | hamma sahifa ƒ / 66 buzilish |
next.config tajribasi |
| Edge, standalone, next/font/google | build xatosi / ortiqcha / tarmoq | Runtime'lar, Deploy |
Bu jadval — loyihaning eng qimmatli qismi. Ish beruvchi "nega X ishlatmadingiz?" deb so'rasa, javob "bilmayman" emas, raqam.
Tekshirib ko'ring: Nega
markedqo'shildi-yu,next-intlning client qismi olib tashlandi? Ikkalasi ham kutubxona-ku.
Javob
marked serverda ishlaydi — brauzerga 0 KB qo'shadi, foyda esa katta (Markdown postlar). next-intl'ning client qismi brauzerga 14.3 KB olib kelardi, lekin brauzerda faqat /en prefiksi kerak edi — o'z kichik Link imiz bilan almashtirildi. Savol "kutubxona yaxshimi?" emas, "u qayerda ishlaydi va qancha turadi?".
4.3 JS'ning yo'li
Brauzer yuklagan JS (bosh sahifa, gzip) bosqichma-bosqich o'sdi. Bo'sh skelet 132.4 → v1 sahifalari 135.4 → client komponentlar 137.4 → modal va next/image 143.4 → tema 143.9 → forma 145.6 → metadata 146.5 → next-intl 161.7 → o'z Link bilan 149.6 KB.
- bo'sh Next skeleti132,4 KB
- /haqimda, /aloqa144,1 KB
- /blog144,7 KB
- /, /loyihalar149,6 KB
- /loyihalar/vazifalarnext/image155,3 KB
Manba: IlmHamroh kanoni, portfolio v2 holat 43, Chrome 155, 2026-10-21
Halol xulosa: v1 bilan solishtirganda Next'ning o'zi ~132 KB qo'shdi. Buning evaziga: HTML serverda tayyor, JS'siz forma va kontent ishlaydi, TTFB 4–12 ms, ikki til, kesh, testlar. Butun portfolio funksionalligi esa skelet ustiga atigi 12–23 KB.
5. Bosqichma-bosqich qurish
5.1 20 commit
Kanon loyihani 20 bosqichda qurdi. Har bosqich — bitta yoki bir nechta dars, bitta commit:
| Darslar | Commit (kanon xabari, qisqartirilgan) |
|---|---|
| #02 | Next: create-next-app 16.4.0 skeleti, versiyalar qotirildi |
| #03–#04 | Sahifalar; umumiy layout va template |
| #05–#06 | not-found, error, loading; joriy havola, teg filtri URL'da |
| #07–#08 | (sayt) guruhi; loyiha rasmi modal'da |
| #09–#11 | Blog: Markdown serverda; Ulashish — client orol |
| #12–#13 | Tema: TemaProvider, bo'yashdan oldingi skript |
| #14–#16 | Haqimda: GitHub profili serverda, Suspense oqimi |
| #17–#19 | Kesh: "use cache", cacheTag; /api/qayta-yangila |
| #20 | DAL: server-only, cache(), DTO |
| #21–#23 | Aloqa: Server Action, Zod, asal idish, tezlik cheklovi |
| #24 | RSS — Route Handler |
| #26–#27 | Proxy: noma'lum slug → 404; after() loglari |
| #29–#30 | SEO: metadata, sitemap, OG rasmlar, JSON-LD |
| #31–#32 | Rubik next/font/local, LCP rasmiga preload |
| #33 | Stil: CSS Module |
| #34 | i18n: next-intl, hreflang |
| #35–#37 | instrumentation, CSP, redirect'lar, env Zod |
| #38 | Perf: o'z Link (−12 KB), animatsiya olib tashlandi |
| #41 | Test: Vitest + Playwright + axe |
| #43 | Docs: README va AGENTS.md |
Har commit'dan oldin bir xil tekshiruv: lint, tur, format, build, testlar, keyin next start ustida har sahifa — status, TTFB, JS, axe, hydration. Shuning uchun xato o'sha bosqichning o'zida ushlangan, oxirida "hammasi buzildi" bo'lmagan.
Tekshirib ko'ring: Nega #43 dagi commit faqat hujjat (README,
AGENTS.md), kod esa holat 41 bilan bir xil?
Javob
Kod #41 da tayyor va testlar bilan himoyalangan edi. Hujjatni alohida commit qilish tarixni toza qiladi: kim git log ga qarasa, "bu commit hech narsani buzmaydi" deb biladi. Aralash commit (kod + hujjat) qaytarish va sharhlashni qiyinlashtiradi.
5.2 14 ta haqiqiy topilma
Qurilish davomida kanon 14 ta kutilmagan narsani topdi — hujjatda yo'q yoki hujjatdan farqli. Ular tegishli darslarda batafsil:
| Topilma | Dars |
|---|---|
| Cache Components build'ni "uncached data" bilan to'xtatadi | Serverda ma'lumot olish, Streaming |
| Noma'lum slug birinchi so'rovda 200 (keyin 404) → proxy bilan tuzatildi | Maxsus fayllar, proxy.ts |
Proxy matcher .png ni ushlagan |
next/font |
Hydration: matn farqi daraxtni qayta yaratadi, checked jim |
Hydration |
try/catch prerender rad etishini yutadi → connection() |
Streaming |
Sahifa openGraph i layout'nikini to'liq almashtiradi |
Metadata API |
<Link locale> ikki header chizadi |
next-intl |
OG rasmda "use cache" — Uint8Array/DataView muammosi |
SEO fayllari |
| SRI qat'iy CSP bilan hydration'ni o'ldiradi (66 buzilish) | next.config |
| Trusted Types client navigatsiyani buzadi | next.config |
SAYT_URL build vaqtida yoziladi |
Env |
| Vitest async RSC'ni chiza olmaydi | Test |
pages/ papkasi hook turlarini | null qiladi |
Yangilash |
axe peer playwright-core 1.64.1 — ikki nusxa, build yiqildi |
Test |
Bu darslarni yozishda biz yana bir nechtasini topdik, ular ham "biz ishga tushirdik" deb belgilangan. Ro'yxat: typedRoutes [locale] bilan deyarli hech narsani tekshirmaydi (next.config), server-only xatosida chalg'ituvchi "Pages Router" matni (Env), faqat translate li animatsiya LCP'ni kechiktirmaydi (Performance), yuk ostida modal e2e testi beqaror (Test).
6. Jonli: loyihaning yuragi — aloqa formasi
Kanondagi AloqaFormasi ning soddalashtirilgan modeli. Haqiqiy loyihada send — Server Action (serverda Zod tekshiruvi, asal idish, tezlik cheklovi). Natija oynasida server yo'q, shuning uchun u oddiy async funksiya. useActionState va forma esa — aynan React'ning o'zi:
import { useActionState } from "react";
type State =
| { status: "idle" }
| { status: "error"; message: string }
| { status: "sent"; name: string };
// Haqiqiy loyihada — "use server" fayldagi Server Action
async function send(_prev: State, form: FormData): Promise<State> {
const name = String(form.get("ism") ?? "").trim();
console.log(`server: ism="${name}"`);
if (name.length < 2) {
return { status: "error", message: "Ismingizni yozing" };
}
return { status: "sent", name };
}
export default function ContactForm() {
const [state, action] = useActionState(send, { status: "idle" });
if (state.status === "sent") {
return <p role="status">Rahmat, {state.name}!</p>;
}
return (
<form action={action}>
<label htmlFor="ism">Ismingiz</label>
<input id="ism" name="ism" />
{state.status === "error" && (
<p role="alert">{state.message}</p>
)}
<button type="submit">Yuborish</button>
</form>
);
}Konsolda:
server: ism=""
server: ism="Malika"Ekranda:
Rahmat, Malika!Birinchi bosish — bo'sh ism, "server" xato qaytardi va forma xabar bilan qoldi. Ikkinchisi — muvaffaqiyat. Haqiqiy portfolio da bu oqim JS o'chiq bo'lsa ham ishlaydi (Playwright testi buni har safar tekshiradi), chunki <form action> — oddiy HTML forma ham (Server Actions I).
7. Sifat: yakuniy tekshiruv
7.1 Raqamlar (holat 43)
| Tekshiruv | Natija |
|---|---|
| lint / tur / format | 0 / 0 / 0 (3 s, 3 s, 1 s) |
| build | 11 s, 63 sahifa prerender |
| Vitest | 10/10 |
| Playwright | 15/15, yana 3 marta 15/15 (8.5–8.7 s, flaky 0) |
| 13 sahifa (uz/en, filtr, modal, 404) | axe 0, hydration 0, TTFB 4–12 ms |
| Regressiya ssenariylari | 9/9 (filtr, modal, tema, forma, RSS, CSP, i18n, SEO, rasm) |
7.2 Lighthouse (mobil, 7 sahifa)
/: perf 98, acce 100, best 100, seo 92 | FCP 0.8 s, LCP 2.4 s, TBT 40 ms, CLS 0, SI 0.8 s
/en: perf 98, acce 100, best 100, seo 92 | FCP 0.8 s, LCP 2.4 s, TBT 60 ms, CLS 0, SI 0.8 s
/haqimda: perf 98, acce 100, best 100, seo 92 | FCP 0.8 s, LCP 2.4 s, TBT 40 ms, CLS 0, SI 0.8 s
/loyihalar: perf 98, acce 100, best 100, seo 92 | FCP 0.9 s, LCP 2.4 s, TBT 40 ms, CLS 0, SI 0.9 s
/loyihalar/vazifalar: perf 97, acce 100, best 100, seo 92 | FCP 0.8 s, LCP 2.6 s, TBT 40 ms, CLS 0, SI 0.8 s
/blog/portfolio-v2: perf 98, acce 100, best 100, seo 92 | FCP 0.8 s, LCP 2.4 s, TBT 40 ms, CLS 0, SI 0.8 s
/aloqa: perf 98, acce 100, best 100, seo 92 | FCP 0.8 s, LCP 2.4 s, TBT 50 ms, CLS 0, SI 0.8 s
Lighthouse 13.5.0, Chrome 155.0.8059.85, mobilSEO 92 — faqat canonical example.com ga ko'rsatgani uchun (lokal o'lchov); to'g'ri SAYT_URL bilan 100 (Performance). Bu yerda "ataylab 100 qilish" emas, sababni bilish muhim.
7.3 Ochiq qolganlar (halol)
Loyiha "mukammal" emas — va buni yozish ham ishning bir qismi:
- Aloqa xabari hozircha faqat logga yoziladi — qayerga yuborish (email, Telegram) backend qismlarida.
- Tezlik cheklovi xotirada — ko'p instansiyada teshik (Deploy I: Vercel).
/enda loyiha va blog matni o'zbekcha (lang="uz"belgisi bilan) — tarjima sizning mashqingiz.- CSP'da
'unsafe-inline'— o'lchangan murosa. - Build'da
metadataBaseogohlantirishi (Next'ning ichki/_not-found) — ta'siri yo'q.
8. README va AGENTS.md
8.1 README
Kanon README'si besh bo'lim: nima bu loyiha, buyruqlar, tuzilma, sozlash (.env.example, SAYT_URL build vaqtida yozilishi), deploy (Vercel va o'z server) va shrift litsenziyasi. Buyruqlar qismi:
npm install
npm run dev # http://localhost:3000
npm run check # lint + tip + format:check + test (Vitest)
npm run build # production build (route jadvali)
npm start # production server
npm run test:e2e # Playwright (avval npm run build)README — loyihaning birinchi sahifasi. GitHub'da repoga kirgan ish beruvchi avval shuni o'qiydi.
8.2 AGENTS.md
Loyiha yaratish darsida AGENTS.md ni ko'rgandingiz — AI kod yordamchilari uchun qo'llanma. Next 16 uning boshiga rasmiy blok qo'yadi: "bu siz bilgan Next.js emas, node_modules/next/dist/docs/ dagi hujjatni o'qing". Kanon uning ostiga loyiha qoidalarini qo'shdi:
- Komponentlar sukut bo'yicha Server Component; "use client" faqat
holat/hodisa/brauzer API kerak bo'lgan barg komponentda.
- Ichki havolalar — @/i18n/navigation dagi Link.
- Fayl/tarmoq o'qish: "use cache" + cacheLife yoki <Suspense>;
argumentsiz new Date() — build xatosi.
- Env faqat src/env.ts orqali (Zod).
- O'zgarishdan keyin: npm run check, npm run build, npm run test:e2e.Kanondan tanlangan qoidalar, qatorlar telefonga sig'ishi uchun bo'lingan. Bu qoidalar — butun qism davomida topilgan saboqlarning qisqa ko'rinishi. Ular faqat AI uchun emas: jamoaga qo'shilgan yangi dasturchi ham aynan shu ro'yxatdan boshlaydi.
8.3 Commit
git add -A
git commitCommit (kanon): Docs: README (tuzilma, sozlash, deploy) va AGENTS.md loyiha qoidalari. Kod holat 41 bilan bir xil — bu commit faqat hujjat.
9. Ko'p uchraydigan xatolar
| Belgi | Sabab | Davosi |
|---|---|---|
| Loyiha oxirida "hammasi buzildi" | Tekshiruv faqat oxirida | Har commit'dan oldin npm run check + build |
| "Nega X ishlatmadingiz?" ga javob yo'q | Tanlovlar yozilmagan | Kirgan/kirmagan jadvali, raqam bilan |
| README faqat create-next-app matni | Hujjat yangilanmagan | Buyruqlar, tuzilma, env, deploy |
Hamma komponent "use client" |
SPA odati | Sukut — Server Component, client — barg |
| Lighthouse 100 uchun ma'nosiz o'zgarish | Raqam maqsadga aylangan | Har yo'qotilgan ball sababini biling |
| Portfolio'da faqat havola | Loyiha hikoyasi yo'q | Case study: muammo, qaror, natija, raqam |
10. Mashqlar
Mashqlar kurs/mashqlar/23/43-yakuniy/ da. Jonli yechimlarni «Ishga tushir» bilan sinang.
1-mashq (oson): qatlamlar
- Sahifalar ma'lumotni qaysi qatlamdan oladi —
- Noma'lum slug'ni 404 ga yuboradigan fayl —
.ts - Env qaysi faylda o'qiladi —
src/.ts - Markdown qayerda HTML'ga aylanadi —
- Faqat bitta dinamik (
ƒ) manzil —/api/
Yechim
- DAL —
malumot/dal.ts,server-onlyvacache()bilan. - proxy — Next 16 da
middlewareo'rnida. - env — Zod bilan,
server-only. - serverda —
markedbrauzerga 0 KB qo'shadi. - qayta-yangila — sirli kesh tozalash; qolgan hammasi
○.
2-mashq (o'rta): forma email bilan
«Aloqa formasi» blokiga email maydonini qo'shing (<label> bilan). "Server" ikkala maydonni tekshirsin: ism kamida 2 belgi, email @ belgisini o'z ichiga olsin. Xato bo'lsa — hamma xatolar bitta role="alert" ichida ; bilan. Sinang: avval faqat ism bilan yuboring, keyin email ham yozing.
Yechim
import { useActionState } from "react";
type State =
| { status: "idle" }
| { status: "error"; errors: string[] }
| { status: "sent"; name: string };
async function send(_prev: State, form: FormData): Promise<State> {
const name = String(form.get("ism") ?? "").trim();
const email = String(form.get("email") ?? "").trim();
const errors: string[] = [];
if (name.length < 2) errors.push("Ismingizni yozing");
if (!email.includes("@")) errors.push("Email noto'g'ri");
console.log(`server: ${errors.length} ta xato`);
if (errors.length) return { status: "error", errors };
return { status: "sent", name };
}
export default function ContactForm() {
const [state, action] = useActionState(send, { status: "idle" });
if (state.status === "sent") {
return <p role="status">Rahmat, {state.name}!</p>;
}
return (
<form action={action}>
<label htmlFor="ism">Ismingiz</label>
<input id="ism" name="ism" />
<label htmlFor="email">Email</label>
<input id="email" name="email" type="email" />
{state.status === "error" && (
<p role="alert">{state.errors.join("; ")}</p>
)}
<button type="submit">Yuborish</button>
</form>
);
}Konsolda:
server: 1 ta xato
server: 0 ta xatoEkranda:
Rahmat, Malika!Harakat qatoriga qarang: ikkinchi yuborishdan oldin ism qayta yozildi. Sababi — React 19: <form action={…}> bilan yuborilgan forma action tugagach o'z maydonlarini avtomatik tozalaydi. Biz avval ismni qayta yozmasdan sinab ko'rdik — natija ikki marta "1 ta xato" bo'ldi: email kiritildi, ism esa bo'sh qolgan edi. Foydalanuvchi uchun bu yoqimsiz: xato chiqdi va yozganlari yo'qoldi. Kanon formasi buni hal qilgan — xato holatida server yuborilgan qiymatlarni qaytaradi (qiymatlar), maydonlar esa ularni defaultValue bilan qayta oladi (Server Actions II).
3-mashq (qiyin): tanlov hisoblagichi
Har texnologiya tanlovini qoida bilan baholaydigan funksiya yozing: decide(option, budgetKb). option — { name, clientKb, benefit }, benefit — "zarur", "foydali" yoki "bezak". Qoida: zarur — doim qabul; foydali — clientKb byudjetga sig'sa qabul; bezak — faqat clientKb === 0 bo'lsa. Har qaror sababi bilan chiqsin. Byudjet — qolgan 10 KB. Kanon raqamlari bilan sinang: marked (0 KB, foydali), next-intl client (14.3 KB, foydali), modal (5.9 KB, foydali), template animatsiyasi (0 KB JS, lekin bezak), React (73.3 KB, zarur).
Yechim
function decide({ name, clientKb, benefit }, budgetKb) {
if (benefit === "zarur") return `${name}: qabul (zarur)`;
if (benefit === "foydali") {
return clientKb <= budgetKb
? `${name}: qabul (${clientKb} KB sig'adi)`
: `${name}: rad (${clientKb} KB > ${budgetKb} KB)`;
}
return clientKb === 0
? `${name}: qabul, lekin o'lchang (bezak)`
: `${name}: rad (bezak)`;
}
const options = [
{ name: "marked", clientKb: 0, benefit: "foydali" },
{ name: "next-intl client", clientKb: 14.3, benefit: "foydali" },
{ name: "modal", clientKb: 5.9, benefit: "foydali" },
{ name: "template animatsiyasi", clientKb: 0, benefit: "bezak" },
{ name: "react-dom", clientKb: 73.3, benefit: "zarur" },
];
for (const o of options) console.log(decide(o, 10));Konsolda:
marked: qabul (0 KB sig'adi)
next-intl client: rad (14.3 KB > 10 KB)
modal: qabul (5.9 KB sig'adi)
template animatsiyasi: qabul, lekin o'lchang (bezak)
react-dom: qabul (zarur)To'rtinchi qator — eng qiziq: animatsiya JS qo'shmaydi, shuning uchun JS byudjeti uni o'tkazdi. Lekin uning narxi boshqa joyda — LCP'da (Performance). Bitta raqam (KB) hamma narxni ko'rsatmaydi; shuning uchun kanon JS ham, Lighthouse ham o'lchadi.
4-mashq: Portfolio qadami — yakun
README.mdni yozing: nima bu, buyruqlar, tuzilma, sozlash, deploy.AGENTS.mdga o'z loyiha qoidalaringizni qo'shing (rasmiy blok ostida).- Yakuniy tekshiruv:
npm run check,npm run build,npm run test:e2e(3 marta), Lighthouse mobil 3 ta sahifada. - "Kirgan va kirmagan texnologiyalar" jadvalini o'zingiz uchun to'ldiring.
- Commit, keyin Vercel'ga deploy (Deploy I) va manzilni README'ga yozing.
vazifalarloyihasi uchun case study yozing — portfolio'dagi birinchi postingiz.
Yechim
Namuna — kanon README va AGENTS.md (yuqorida). Case study besh qismdan iborat. (1) Muammo — nima uchun bu ilova. (2) Texnologiyalar va nega. (3) Eng qiyin joy va qanday hal qilingan (masalan 22-qismda vizual test topgan «Qayta urinish» tugmasi xatosi). (4) Raqamlar — testlar soni, Lighthouse, bundle hajmi. (5) Nimani boshqacha qilardingiz. Raqamsiz case study — reklama; raqamli — muhandislik hujjati. Yakuniy tekshiruvdagi har ogohlantirishni README'ning "Ma'lum cheklovlar" bo'limiga yozing.
11. Real ishda
- Portfolio — ishga kirish hujjati. Junior vakansiyada ish beruvchi ko'pincha bitta loyihani chuqur ko'radi: kod tuzilmasi, commit tarixi, README, testlar.
portfoliov2 aynan shunday loyiha: 20 ma'noli commit, testlar, o'lchangan raqamlar. - Texnik intervyu "loyihangiz haqida gapirib bering" bilan boshlanadi. Tanlovlar jadvali va 14 topilma — tayyor hikoyalar: "Biz SRI'ni sinadik, hydration o'ldi, shuning uchun…".
- ADR (Architecture Decision Record — arxitektura qarori yozuvi) — katta jamoalarda har muhim tanlov shunday hujjatlanadi. Bu darsdagi jadval — uning kichik ko'rinishi; arxitektura qismida batafsil.
- Davomi: 39-qismda portfolio'ga yana case study'lar va CV qo'shiladi; backend qismlaridan keyin aloqa formasi haqiqiy manzilga xabar yuboradi.
Xulosa
portfoliov2 — 23-qismning hamma g'oyasi bitta loyihada: 63 statik sahifa, bittaƒAPI, ikki til, JS'siz ishlaydigan forma.- Arxitektura: proxy → sahifalar → Server Components va client orollar → DAL → manbalar; env faqat
env.ts. - Har tanlov o'lchangan: kirmaganlar (Tailwind, MDX, nonce CSP, Edge…) ham sababi va raqami bilan yozilgan.
- Natija: Lighthouse 97–98 / 100 / 100, axe 0, hydration 0, Vitest 10, Playwright 15, JS 144–155 KB.
- 20 commit, har biridan oldin bir xil tekshiruv; 14 haqiqiy topilma darslarda saboqqa aylangan.
- README va
AGENTS.md— loyihani boshqalar (va siz o'zingiz, bir yildan keyin) davom ettira olishi uchun.
Keyingi dars: Node.js nima: runtime, V8 va libuv — 24-qism: endi server tomoniga to'liq o'tamiz. Next ichida ko'rgan node:fs, jarayon va oqimlarni o'zi alohida o'rganamiz.
Manbalar
- Next.js hujjati (16.4.0 bilan kelgan nusxa,
node_modules/next/dist/docs/), 2026-10-21 da o'qildi: https://nextjs.org/docs - Kanon:
portfoliov2 (holat 43) — README,AGENTS.md,package.json; yakuniy tekshiruv, Lighthouse 13.5.0 (7 sahifa, mobil), e2e 3 marta, regressiya ssenariylari (2026-10-21); kurs qarorlari (CSP V1, next-intl serverda,/enmatni, animatsiya "narxi"). - Bu qism darslarida biz qo'shimcha ishga tushirgan tajribalar: typedRoutes,
NEXT_PUBLIC_inlining,.envtartibi,server-onlyxatosi, animatsiya uch varianti, codemod, e2e takrorlari (next 16.4.0, Node 24.21.0, Chrome 155).
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!