IlmHamroh
JavaScript Full-stack/16-qism. Frontend asboblari: npm, bundlerlar, config1/48-dars23 daqiqa
Mundarija (31)

Frontend asboblar zanjiri: manba koddan brauzergacha

Qisqacha: Brauzer faqat HTML, CSS va JavaScript'ni tushunadi. Biz esa TypeScript, modullar va npm paketlari bilan yozamiz. Kodni brauzerga tayyorlaydigan vositalar ketma-ketligi — asboblar zanjiri (toolchain). npm paketlarni olib keladi, tsc tekshiradi, bundler (masalan Vite) kodni yig'ib, siqib, dist/ ga yozadi. GitHub Pages esa dist/ ni CDN orqali tarqatadi. 16-qismda vazifalar shu zanjirga o'tadi: brauzer yuklaydigan kod 85.8 KB dan 38.1 KB ga, fayllar 20 tadan 4 taga tushadi.

Bu darsda

  • Brauzer nega .ts va .tsx ni bajarmasligini haqiqiy xato xabarlari bilan tushuntira olasiz.
  • Zanjirning har halqasi (paket menejeri, tekshiruvchi, transpiler, bundler, minifikator, deploy) nima qilishini ayta olasiz.
  • Dev server va build farqini, src/, node_modules/, dist/ vazifasini bilasiz.
  • vazifalar ning bugungi (v5) va 16-qism oxiridagi (v6) zanjirini solishtira olasiz.
  • 16-qism bloklari vazifalar ga nima berishini bilasiz.

Oldin bilishingiz kerak: npm'ga birinchi qadam, TypeScript build: tsc, bundler'lar va tsgo, GitHub Pages'ga Actions orqali deploy, HTTP sarlavhalari, MIME turlari va kesh.

1. Nega bu kerak?

15-qismning oxirgi darsida vazifalar v5 ni yakunladik: 2 721 qator TypeScript, 143 test, Lighthouse 100. Endi 16-qism boshlanadi. Bu qismda yangi til o'rganmaymiz. Bu qism — asboblar haqida: kodni yozishdan saytga chiqarishgacha uni kim, qanday qayta ishlaydi.

Nega bu alohida qism? Bir voqea. Jasur aka «Bahor» uchun boshqa dasturchilar yozgan yangi menyu loyihasini oldi va Sardorga berdi. Sardor uni GitHub'dan yuklab, papkani ochdi. Ichida package.json da 30 dan ortiq paket, vite.config.ts, tsconfig.app.json, .nvmrc, .husky/ papkasi bor edi. src/ ichida esa .tsx fayllar.

Sardor index.html ni ikki marta bosib ochdi. Sahifa bo'sh. Keyin npm run build buyrug'ini topdi, dist/index.html ni ochdi — yana bo'sh. Konsolda qizil xatolar. Kod ishlaydi — boshqa dasturchilarda ishlagan. Sardor esa loyihaga qanday "kirishni" bilmaydi.

Bu dars — xarita. Har fayl va har buyruq zanjirning qaysi halqasiga tegishli ekanini bilsangiz, notanish loyiha qo'rqinchli bo'lmaydi. Keyingi 47 dars har halqani chuqur ochadi.

Hayotiy o'xshatish: «Bahor» oshxonasi. Mijozning stoliga faqat tayyor osh keladi. Undan oldin esa bozor, ombor, sifat nazorati, oshpaz va ofitsiant bor. Mijoz ularni ko'rmaydi, lekin bittasi buzilsa — osh ham yo'q. Frontend'da mijoz — brauzer, osh — dist/ dagi fayllar.

2. Brauzer nimani tushunadi

2.1 Uch til va boshqa hech narsa

Brauzer HTML, CSS va JavaScript'ni tushunadi. Yana rasm, shrift, WebAssembly kabi tayyor formatlarni ham. TypeScript ular orasida yo'q. JSX (React'ning HTML'ga o'xshash yozuvi — 17-qismda o'rganamiz, hozir bilish shart emas) ham yo'q. .tsx — TypeScript va JSX bir faylda, demak brauzer uchun ikki karra begona.

Keling, tekshirib ko'ramiz. Mana oddiy TypeScript fayli app.ts:

ts
const price: number = 35000;
console.log("narx", price); // narx 35000

Node 24 uni bajaradi: TypeScript'ni o'rnatish darsida ko'rganimizdek, u turlarni o'chirib tashlaydi. Endi shu faylni brauzerga beramiz:

html
<script type="module" src="./app.ts"></script>

2.2 Tajriba: brauzerga .ts va .jsx beramiz

Biz bu sahifani Chrome 154 da uch xil holatda ochdik (kichik lokal server orqali). Har holatda konsolda chiqqan haqiqiy xabar:

Server faylni qanday yubordi Chrome 154 konsolida
app.ts, Content-Type: video/mp2t Failed to load module script (MIME)
app.ts, Content-Type: text/javascript SyntaxError: Missing initializer in const declaration
app.jsx, Content-Type: text/javascript SyntaxError: Unexpected token '<'

Birinchi holat — eng ko'p uchraydigani. Birinchi qatordagi to'liq xabar:

text
Failed to load module script: Expected a JavaScript-or-Wasm module script but the server responded with a MIME type of "video/mp2t". Strict MIME type checking is enforced for module scripts per HTML spec.

Tarjimasi: "Modul skriptini yuklab bo'lmadi: JavaScript yoki Wasm moduli kutilgan edi, server esa video/mp2t MIME turini yubordi. Modul skriptlari uchun MIME turi qat'iy tekshiriladi".

Nega video? .ts kengaytmasi TypeScript'dan oldin ham bor edi: u MPEG-TS video formati (televidenie oqimlari). Ko'p serverlar kengaytmaga qarab turni tanlaydi. Masalan, Node'dagi Express ishlatadigan mime-types paketi app.ts uchun video/mp2t qaytaradi — buni ham tekshirdik. MIME turlari darsidan bilasiz: brauzer faylni nomiga emas, Content-Type sarlavhasiga qarab o'qiydi.

Ikkinchi holatda server "bu JavaScript" dedi va brauzer const price: dagi ikki nuqtaga qoqildi. Xabar "const e'lonida boshlang'ich qiymat yo'q" deydi. Chalg'ituvchi, to'g'rimi? JavaScript const price dan keyin = kutgan edi, : ni esa tushunmadi. Uchinchi holatda < — JavaScript'da "kichik" operatori, = dan keyin esa ma'nosiz:

jsx
const title = <h1>Bahor</h1>;
console.log(title);

Xulosa: brauzerga yetib boradigan har fayl oddiy JavaScript bo'lishi shart. Turlar, JSX, import "web-vitals" kabi paket nomlari — hammasi avval qayta ishlanishi kerak.

Tekshirib ko'ring: Node 24 node app.ts ni bajaradi, Chrome 154 esa app.ts ni bajarmaydi. Nega farq bor?

Javob

Node 24 ga turlarni o'chirish imkoniyati (type stripping) qo'shilgan: u : number ni o'zi olib tashlab, qolganini bajaradi. Brauzerlarda bunday imkoniyat yo'q — ular faqat standart JavaScript'ni bajaradi. Shuning uchun brauzer uchun kodni oldindan, kompyuterimizda aylantirib qo'yamiz.

3. Asboblar zanjiri

3.1 Toolchain nima

Asboblar zanjiri (toolchain) — manba kodni brauzerga yetkaziladigan fayllarga aylantiradigan vositalar ketma-ketligi. Har vosita bitta ishni qiladi va natijani keyingisiga uzatadi. Xuddi oshxonadagi kabi: bozorchi go'shtni olib keladi, oshpaz pishiradi, ofitsiant olib boradi.

Manba kod (source code) — siz yozadigan va o'qiydigan kod: src/*.ts, index.html, CSS. U odam uchun: izohlar, uzun nomlar, ko'p fayllar. Zanjir oxirida esa mashina uchun fayllar chiqadi: kam, kichik, izohsiz.

Diagrammaga qarang: chap tomonda siz yozadigan narsa, o'ng tomonda brauzer oladigan narsa. O'rtadagi har to'rtburchakni 16-qismda alohida o'rganamiz.

flowchart TB
  S["src/*.ts<br/>index.html, CSS"] --> N["npm<br/>node_modules/"]
  N --> T["tsc, ESLint<br/>tekshiradi"]
  T --> V["Vite: Oxc + Rolldown<br/>o'giradi, yig'adi"]
  V --> M["minifikatsiya<br/>+ hash"]
  M --> D["dist/<br/>4 ta fayl"]
  D --> P["GitHub Pages<br/>CDN"]
  P --> B["brauzer"]

3.2 Halqalar birma-bir

Halqa Nima qiladi Bizdagi vosita
Paket menejeri Begona kodni yuklab, node_modules/ ga qo'yadi npm 11
Tekshiruvchilar Xatoni topadi, kodni o'zgartirmaydi tsc, ESLint, Prettier, node --test
Transpiler TS va yangi JS ni brauzer JS'iga o'giradi Oxc (Vite ichida)
Bundler Ko'p modulni bir necha faylga yig'adi Rolldown (Vite ichida)
Halqa Nima qiladi Bizdagi vosita
Minifikator Bo'sh joy, izoh, uzun nomlarni olib tashlaydi Oxc, Lightning CSS
Hash Fayl nomiga tarkib "barmoq izi"ni qo'shadi Vite
Deploy va CDN dist/ ni internetga chiqaradi GitHub Pages (Actions)

Jadval telefonga sig'ishi uchun ikkiga bo'lingan. Atamalarni bittalab ochamiz.

Paket menejeri (package manager) — boshqalar yozgan kodni (paketlarni) yuklab oladigan va versiyasini kuzatadigan dastur. Siz npm bilan birinchi qadam darsida tanishgansiz: npm install paketlarni node_modules/ ga qo'yadi. 16-qismda npm'ga 17 ta dars ajratilgan — eng katta blok.

Transpiler — tsc va bundler'lar darsidan tanish: kodni boshqa tilga yoki boshqa versiyaga o'giradigan dastur, turlarni tekshirmaydi. Vite 8 ichida bu ishni Oxc (Rust'da yozilgan vosita) qiladi.

Bundler (yig'uvchi) — ko'p modulni import zanjiri bo'yicha kuzatib, bir yoki bir necha faylga birlashtiradigan vosita. Vite 8 ichida bu Rolldown (u ham Rust'da). Bundler kutubxonadan ishlatilmagan kodni ham tashlab yuboradi — buni Tree shaking darsida ko'ramiz.

Minifikatsiya (minification) — kodning ma'nosini o'zgartirmay, hajmini kichraytirish: bo'sh joylar, izohlar o'chadi, ichki nomlar bir harfga qisqaradi. Oshxona tilida: osh o'sha-o'sha, faqat ixcham qopqoqli idishga solingan.

Hash — fayl tarkibidan hisoblangan qisqa "barmoq izi": index-C4s8yKGl.js. Tarkib bir harf o'zgarsa, iz ham o'zgaradi. Nega kerakligini pastroqda, raqamlar bilan ko'ramiz.

3.3 Hammasi Node'da ishlaydi

Zanjirning bitta qiziq tomoni bor. Natija brauzer uchun, lekin vositalarning hammasi — npm, tsc, ESLint, Vite — sizning kompyuteringizda, Node.js ichida ishlaydi. Shuning uchun Node versiyasi ham zanjirning bir qismi. Bir dasturchida Node 22, boshqasida Node 24 bo'lsa, bir xil loyiha ikki xil natija berishi mumkin. Buni keyingi darsda hal qilamiz.

Tekshirib ko'ring: Transpiler va bundler ikkalasi ham "kodni o'zgartiradi". Farqi nimada?

Javob

Transpiler har faylni alohida o'giradi: .ts dan turlarni olib tashlaydi, yangi sintaksisni eskisiga aylantiradi. Fayllar soni o'zgarmaydi. Bundler esa fayllar orasidagi import larni kuzatadi va ularni birlashtiradi: 15 ta modul bitta faylga aylanishi mumkin. Vite ikkalasini ham qiladi, lekin ichida ikki xil vosita ishlaydi (Oxc va Rolldown).

4. Ikki rejim: dev va build

Zanjir ikki rejimda ishlaydi: kod yozayotganda (natija darhol kerak) va saytni mijozga chiqarishda (natija kichik va tez bo'lishi kerak).

4.1 Dev server: yozayotganda

Dev server (ishlab chiqish serveri) — kod yozayotganda ishlatiladigan lokal server. U fayllarni oldindan yig'maydi: brauzer qaysi faylni so'rasa, o'shani o'sha zahoti o'giradi.

npm run dev ni vazifalar ga 16-qism o'rtasida qo'shamiz. Hozir uni oldindan ko'ramiz (16-qism oxiridagi loyihaning haqiqiy chiqishi):

bash
npm run dev
text
> dev
> vite --port 5397 --strictPort


  VITE v8.3.3  ready in 759 ms

  ➜  Local:   http://localhost:5397/
  ➜  Network: use --host to expose

Port raqamini biz alohida tanladik. Sukut bo'yicha Vite 5173 ni oladi. 759 ms — ishga tushish vaqti, sizda boshqa raqam chiqadi.

Endi brauzer src/vazifa.ts ni so'raganda nima bo'lishini kuzatamiz. Manba faylda turlar bor:

ts
export class VazifaXatosi extends Error {
  readonly kod: VazifaXatosiKodi;

  constructor(
    xabar: string,
    sozlama?: ErrorOptions & { kod?: VazifaXatosiKodi },
  ) {
    super(xabar, sozlama);

Dev server esa xuddi shu manzil (/src/vazifa.ts) bo'yicha Content-Type: text/javascript sarlavhasi bilan quyidagini qaytardi:

js
export class VazifaXatosi extends Error {
	kod;
	constructor(xabar, sozlama) {
		super(xabar, sozlama);

Turlar va readonly yo'q, qolgani o'sha-o'sha. Nom .ts bo'lib qoldi, ichidagisi esa JavaScript — brauzer sarlavhaga qaraydi, shuning uchun ishlaydi.

Dev server'ning yana bir kuchi — HMR (Hot Module Replacement, modulni issiq almashtirish): faylni saqlasangiz, sahifa qayta yuklanmaydi, faqat o'zgargan modul almashadi. Batafsil — Vite I darsida.

4.2 Build: mijozga chiqarishdan oldin

Build (yig'ish) — loyihani bir marta, oxirigacha qayta ishlab, tayyor fayllarni papkaga yozish. Natija odatda dist/ (distribution — "tarqatish uchun") papkasiga tushadi. Shu papka saytga chiqadi.

16-qism oxirida vazifalar ning buildi shunday ko'rinadi (haqiqiy chiqish, ranglar olib tashlangan). Chiqish uzun, lekin hozir faqat dist/ bilan boshlanadigan beshta qatorga qarang: ular — brauzerga boradigan fayllar va ularning hajmi.

bash
npm run build
text
> build
> tsc -b && vite build

vite v8.3.3 building client environment for production...
transforming...
<script src="assets/js/tema.js"> in "/index.html" can't be bundled without type="module" attribute
✓ 23 modules transformed.
rendering chunks...
computing gzip size...
dist/index.html                  5.27 kB │ gzip: 1.89 kB
dist/assets/index-BI1hyTgJ.css   3.59 kB │ gzip: 1.29 kB
dist/assets/js/tema.js           0.16 kB │ gzip: 0.15 kB │ map:   0.94 kB
dist/assets/olchov-G4bloHwN.js   8.92 kB │ gzip: 3.42 kB │ map:  22.87 kB
dist/assets/index-C4s8yKGl.js   25.38 kB │ gzip: 9.51 kB │ map: 115.37 kB

✓ built in 638ms
sw.js: QOBIQ — 12 ta, VERSIYA — v6-755dc5da

Qo'rqmang — har qatorni keyingi darslarda ochamiz. Hozir faqat asosiylarini ko'ring:

  • tsc -b && vite build — avval tsc tekshiradi, xato bo'lmasa Vite yig'adi. && — "oldingisi muvaffaqiyatli bo'lsa, keyingisini bajar". Vite turlarni tekshirmaydi — tsc va bundler'lar darsidagi "tekshirish va yozishni ajratish" qoidasi shu.
  • 23 modules transformed — 23 ta modul o'girildi. Natijada 3 ta JavaScript va 1 ta CSS fayl chiqdi.
  • gzip: 9.51 kB — gzip — server fayllarni tarmoq orqali yuborishdan oldin siqadigan usul (HTTP sarlavhalari darsidagi Content-Encoding). Vite siqilgan hajmni ham ko'rsatadi, chunki foydalanuvchi aynan shuni yuklab oladi.
  • index-C4s8yKGl.js — nomdagi C4s8yKGl — hash.
  • map: 115.37 kB — source map (manba xaritasi): siqilgan koddagi xatoni manba qatoriga qaytaradigan fayl (Source map'lar).
  • Ogohlantirish (can't be bundled) — ataylab qoldirilgan. Uni Bundler nima darsida tushuntiramiz.
  • Oxirgi qator — Service Worker uchun yozgan o'z plaginimizning xabari (Vite plaginlari).

638ms — vaqt, sizda boshqacha bo'ladi.

4.3 Uch papka: src/, node_modules/, dist/

Har zamonaviy frontend loyihada shu uch papkani ko'rasiz. Ularni adashtirish — boshlovchining eng ko'p uchraydigan xatosi.

Papka Ichida nima Kim yozadi Git'ga
src/ Manba kod Siz Ha
node_modules/ Paketlar va ularning paketlari npm install Yo'q
dist/ Build natijasi npm run build Yo'q

node_modules/ va dist/ ni bitta buyruq bilan qayta yasash mumkin, shuning uchun ular .gitignore da turadi. Git'da faqat ularning "retsepti" saqlanadi: package.json, package-lock.json, manba kod va config fayllar.

node_modules/ qancha joy oladi? Biz o'lchadik (du -sm, Windows 11, npm 11.19.0):

Loyiha node_modules/
vazifalar v5 (bugun) 86 MB
vazifalar v6 (16-qism oxirida) 168 MB

Bu — asboblarning narxi: Vite, commitlint, husky, knip va ularning bog'liqliklari. Lekin ularning hech biri brauzerga bormaydi — brauzerga faqat dist/ boradi.

Tekshirib ko'ring: Sardor dist/assets/index-C4s8yKGl.js faylini ochib, xatoni o'sha yerda tuzatdi. Ertasiga u yana npm run build qildi. Tuzatish nima bo'ladi?

Javob

Yo'qoladi. Build dist/ ni har safar boshidan yozadi — manba (src/) dan. dist/ dagi o'zgarish hech qayerga saqlanmaydi. Tuzatish har doim src/ da qilinadi. Bundan tashqari, tarkib o'zgargani uchun yangi buildda fayl nomidagi hash ham boshqacha bo'ladi.

5. vazifalar: bugun va 16-qism oxirida

5.1 Bugungi zanjir — v5

15-qismda vazifalar ga eng sodda zanjirni qurgan edik: tsc har .ts faylni alohida .js ga aylantiradi, nusxala.js qolgan fayllarni ko'chiradi. Haqiqiy chiqish — undagi hajmlar yo'qligiga e'tibor bering: v5 build nima yozganini aytmaydi.

bash
npm run build
text
> prebuild
> node -e "fs.rmSync('dist', { recursive: true, force: true })"


> build
> tsc && node skriptlar/nusxala.js

dist/ ga ko'chirildi: 6 ta

dist/ da 29 ta fayl. Ulardan 21 tasi JavaScript va CSS. Brauzer sahifani ochganda ulardan 20 tasini alohida so'raydi (turlar.js — build'dan keyin bo'sh modul: undagi turlar faqat import type bilan olinadi). Har modul — alohida so'rov, alohida fayl, ichida izohlar va bo'sh joylar bilan.

Bu yomon emas: Lighthouse 100 edi. Lekin modullar ko'paygan sari so'rovlar ham ko'payadi. npm paketini esa bu zanjir tushunmaydi: brauzer import "web-vitals" ni qayerdan izlashni bilmaydi. Shuning uchun web-vitals ni qo'lda vendor/ papkasiga ko'chirgan edik.

5.2 16-qism oxiridagi zanjir — v6

16-qismda vazifalar 18 ta qadamda yangi zanjirga o'tadi:

flowchart LR
  subgraph V5["v5: bugun"]
    direction TB
    A1["19 ta .ts"] --> A2["tsc: tekshiradi<br/>va yozadi"]
    A2 --> A3["dist/: 21 ta<br/>JS va CSS"]
  end
  subgraph V6["v6: 16-qism oxirida"]
    direction TB
    B1["src/: 19 ta .ts"] --> B2["tsc -b:<br/>faqat tekshiradi"]
    B2 --> B3["vite build: o'giradi,<br/>yig'adi, siqadi"]
    B3 --> B4["dist/: 4 ta<br/>JS va CSS"]
  end
  V5 ~~~ V6

Ikki ustunni solishtiring. Chapda (v5) tsc ikki ishni qiladi. O'ngda (v6) ish bo'lingan: tsc faqat tekshiradi, JavaScript'ni Vite yozadi. Eng katta farq pastda: 21 o'rniga 4 ta fayl.

5.3 Raqamlar: qayerga boramiz

Ikkala dist/ ni o'lchadik: brauzer yuklaydigan JavaScript va CSS (Service Worker'siz), xom hajm va gzip (-9) bilan. Bu raqamlarni o'zingiz ham 3-mashqda chiqarasiz.

vazifalar: brauzer yuklaydigan JS + CSS (gzip)
  • v5: tsc, bundlersiz20 ta so'rov32 KB
  • v6: tsc -b + vite build4 ta so'rov, −56 %14,3 KB

Manba: O'lchandi: vazifalar v5 va v6 dist/, gzip -9, Node 24.21.0, Vite 8.3.3, 2026-10-07

v5 (bugun) v6 (16-qism oxiri)
JS + CSS, xom 85.8 KB 38.1 KB
JS + CSS, gzip 32.0 KB 14.3 KB
Fayllar (so'rovlar) 20 4
Lighthouse FCP / LCP 1.3 s / 1.8 s 1.1 s / 1.5 s

Oxirgi qator — Lighthouse 13.5.0 ning mobil o'lchovi (Chrome 154, gzip bilan). FCP (birinchi matn yoki rasm chiqqan vaqt) va LCP (eng katta element chiqqan vaqt) ni Core Web Vitals darsidan bilasiz. Ball ikkalasida 100. Lekin sahifa 0.3 soniya tezroq to'liq chiziladi.

Halol bo'laylik: yutuq bepul emas. node_modules/ 86 MB dan 168 MB ga o'sadi, ildizga yangi config fayllar qo'shiladi. Shuning uchun har qadamda so'raymiz: "bu asbob o'z narxini oqlaydimi?". Masalan, 15-qismda Zod'ni "bundler bilan qayta ko'ramiz" degan edik. O'lchaymiz va uch maydonli tekshiruvimizga kutubxona kerak emasligini ko'ramiz (Paket tanlash).

5.4 Minifikatsiya va hash — ko'z bilan

vazifa.ts dagi VazifaXatosi klassi build'dan keyin dist/assets/index-C4s8yKGl.js ichida shunday ko'rinadi (bitta uzun qatorning bir bo'lagi):

text
var e=class extends Error{kod;constructor(e,t){super(e,t),this.name=`VazifaXatosi`,this.kod=t?.kod??`NOMALUM`}},t=class e{static MAKS_UZUNLIK=100;id;bajarildi;#e;constructor(e,t,n=!1){this.id=e,this.#e=t,this.bajarildi=n}s

Nimalar o'zgardi:

  • xabar va sozlama — e va t bo'ldi. Ichki nomlar tashqariga ko'rinmaydi, shuning uchun ularni qisqartirish xavfsiz.
  • false — !1 bo'ldi (uch belgi kam, ma'nosi bir xil).
  • Izohlar, bo'sh joylar, qator ko'chishlari — yo'q. Butun fayl bitta qator.
  • Xabar matnlari ("NOMALUM") va xususiyat nomlari (bajarildi) saqlandi — ularsiz dastur buziladi.

Endi hash. Brauzer yuklangan fayllarni keshda saqlaydi, toki keyingi safar qayta yuklamasin. Muammo: siz kodni yangiladingiz, foydalanuvchi esa keshdagi eski app.js ni ishlataveradi. Hash buni yechadi: tarkib o'zgarsa — nom o'zgaradi va brauzer uni yangi fayl deb yuklaydi. Tarkib o'zgarmasa — nom ham o'sha, kesh ishlayveradi. Batafsil — Code splitting va hash bilan keshlash darsida.

5.5 Oxirgi halqa: Pages va CDN

dist/ tayyor. 15-qismdan beri GitHub Actions uni GitHub Pages'ga yuklaydi (Actions orqali deploy). Lekin Pages fayllarni bitta kompyuterdan bermaydi.

CDN (Content Delivery Network — kontent yetkazish tarmog'i) — dunyoning turli shaharlaridagi serverlar to'plami. Ular saytingiz fayllarining nusxasini saqlaydi va foydalanuvchiga eng yaqinidan beradi. CDN'ni Internet darsida qisqa ko'rgansiz. Bu xuddi «Bahor»ning shahar bo'ylab filiallari kabi: mijoz markaziy oshxonaga emas, eng yaqin filialga boradi.

GitHub Pages'dagi istalgan saytning sarlavhalarida buni ko'rish mumkin. Terminaldan tarmoqni tekshirish darsidagi curl -I bilan GitHub'ning o'z Pages sahifasini so'radik (faqat kerakli qatorlar):

bash
curl -sI https://pages.github.com/
text
Server: GitHub.com
Cache-Control: max-age=600
Via: 1.1 varnish
Age: 60
X-Served-By: cache-ams-eham8680022-AMS
X-Cache: HIT
  • X-Served-By: cache-ams-… — javobni Amsterdam'dagi (AMS) kesh serveri berdi. Sizda boshqa shahar chiqishi mumkin.
  • X-Cache: HIT — fayl kesh serverda bor edi, asosiy serverga borilmadi.
  • Cache-Control: max-age=600 — brauzer faylni 600 soniya (10 daqiqa) eski hisoblamaydi. Pages'da bu qiymatni o'zgartirib bo'lmaydi. Buni hash bilan keshlash darsida yana eslaymiz.

Tekshirib ko'ring: Nega v6 da so'rovlar soni 20 dan 4 ga tushgani muhim, agar har fayl kichik bo'lsa ham?

Javob

Har so'rovning o'z narxi bor: so'rov yuborish, javobni kutish, sarlavhalar. Ayniqsa modullarda brauzer avval bitta faylni oladi, undagi import larni o'qiydi, keyin keyingilarini so'raydi — zanjir bo'lib. Sekin mobil internetda bu kutishlar qo'shilib boradi. Bundler modullarni oldindan birlashtiradi, shuning uchun brauzer hamma kerakli kodni kam so'rov bilan oladi.

6. 16-qism xaritasi

16-qism 48 darsdan iborat. Ularni yetti blokka bo'lish mumkin. Har blok zanjirning bir qismini ochadi va vazifalar ga aniq bir narsa qo'shadi. Jadvaldagi #02 kabi raqamlar — "Vazifalar qadami" bo'lgan darslar.

Darslar Blok vazifalar ga nima qo'shiladi
01–02 Zanjir va Node versiyasi .nvmrc, engines (#02)
03–19 npm va paketlar npm run check (#06), .npmrc va imzo tekshiruvi (#16)
20–25 Bundler asoslari vite build (#20), brauzerlar ro'yxati (#22), source map (#24)
26–32 Vite dev va preview (#26), .env (#28), src/ (#29), tahlil (#30), o'z plagini (#31), proxy (#32)
Darslar Blok vazifalar ga nima qo'shiladi
33–35 Boshqa bundlerlar va SVG — (o'qish va mashq)
36–41 Kod sifati asboblari tur bilan ishlaydigan ESLint (#38), commitlint (#40), Git hook'lar (#41)
42–48 Config fayllar va orientatsiya tsconfig bo'linishi (#42), ildiz fayllari (#44), knip (#48)

Har blok nimani o'rgatadi:

  • npm va paketlar — package.json maydonlari, versiyalar, lock-fayl, pnpm/Yarn/Bun, paket tanlash va xavfsizlik.
  • Bundler asoslari — bog'liqlik grafi, polyfill, tree shaking, code splitting — Vite'siz, tushuncha sifatida.
  • Vite — config, rejimlar, plaginlar. vazifalar eng ko'p shu yerda o'zgaradi.
  • Boshqa bundlerlar — eski loyihadagi webpack config'ini o'qish va 2026-yil manzarasi.
  • Kod sifati — ESLint va Prettier chuqur, Biome, commit qoidalari, hook'lar.
  • Config fayllar — notanish repoga 15 daqiqada "kirish". Sardorning muammosi shu yerda to'liq yechiladi.

To'rt dars (#09, #23, #25, #43) kodni o'zgartirmaydi — ularda faqat o'lchaymiz. React'ga (17-qism) vazifalar aynan 16-qism oxiridagi tuzilmada o'tadi.

7. Ko'p uchraydigan xatolar

7.1 dist/index.html ni ikki marta bosib ochish

Sardor build qildi va dist/index.html ni Explorer'dan ochdi. Sahifa bo'sh, konsolda (yo'l qisqartirildi):

text
Access to script at 'file:///…/dist/assets/index-C4s8yKGl.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: chrome, chrome-experimental-site-token-provider, chrome-extension, chrome-untrusted, data, http, https, isolated-app.

Tarjimasi: "null origin'dan skriptga kirish CORS siyosati bilan to'sildi: boshqa manbadan so'rov faqat ro'yxatdagi protokollar uchun ruxsat etilgan" — file: esa ro'yxatda yo'q. Xuddi shu xabar CSS va manifest uchun ham chiqdi.

Sabab: file:// dan ochilgan sahifaning origin'i null (Origin va Same-Origin Policy). Modul skriptlari esa CORS qoidasi bilan yuklanadi. Vite <link> ga ham crossorigin atributini qo'yadi — shuning uchun CSS ham yuklanmadi.

Tuzatish: build natijasini server orqali oching. 16-qismda buning uchun npm run preview qo'shamiz (Vite I). Hozircha VS Code'dagi Live Server ham yetadi.

7.2 node_modules/ ni ko'chirish yoki git'ga qo'shish

168 MB ni arxivlash shart emas. Bundan tashqari, ba'zi paketlar operatsion tizimga xos tayyor dastur (binar) o'rnatadi: Windows'dagi node_modules Linux'da ishlamasligi mumkin. To'g'ri yo'l: package.json va package-lock.json ni bering, u yerda npm ci qilinsin (Lock-fayllar va npm ci).

7.3 "Build o'tdi — demak hammasi to'g'ri"

Vite turlarni tekshirmaydi: tsc siz build tur xatosi bilan ham "muvaffaqiyatli" bo'ladi. 16-qismda yana bir misol ko'ramiz: .env.production o'chirilsa, build o'tadi, lekin saytda API manzili undefined (Vite III: env). Asbob faqat o'ziga aytilganini tekshiradi — shuning uchun tekshiruvchilar alohida halqa.

8. Mashqlar

1-mashq (oson): Halqani toping

Har ish uchun zanjirning qaysi halqasi javob beradi?

  1. import "web-vitals" dagi paketni internetdan yuklab olish — .
  2. price: number dan : number ni olib tashlash — .
  3. 23 ta modulni 3 ta faylga birlashtirish — .
  4. xabar nomini e ga qisqartirish — .
  5. Fayl nomiga C4s8yKGl qo'shish — .
Yechim
  1. Paket menejeri (npm) — node_modules/ ga yuklaydi.
  2. Transpiler (Vite ichida Oxc). tsc ham buni qila oladi, lekin v6 da u faqat tekshiradi.
  3. Bundler (Vite ichida Rolldown).
  4. Minifikator (Vite 8 da sukut bo'yicha Oxc).
  5. Hash — Vite fayl tarkibidan hisoblaydi.

E'tibor bering: 2–5 ning hammasini bitta buyruq — vite build qiladi. Vite — bitta asbob emas, zanjirning bir nechta halqasini birlashtirgan "kombayn".

2-mashq (o'rta): v5 dist/ ni o'rganing

O'z vazifalar loyihangizda (15-qism oxiridagi holat):

  1. npm run build ni bajaring.
  2. dist/ da nechta fayl borligini sanang. Git Bash'da: find dist -type f | wc -l (find fayllarni topadi, wc -l qatorlarni sanaydi).
  3. dist/assets/js/vazifa.js ni oching. Manba vazifa.ts dan nimasi bilan farq qiladi?
  4. dist/index.html ni Live Server bilan oching, DevTools → Network → JS filtri. Nechta JavaScript fayli yuklandi?
Yechim

1–2. Bizning loyihada find dist -type f | wc -l — 29. Ulardan 20 tasi .js (vendor/web-vitals.js bilan), bittasi .css, bittasi sw.js; qolgani index.html, manifest va 5 ta ikon.

  1. tsc turlarni olib tashlagan, qatorlarni 4 bo'sh joy bilan surgan. Izohlar va nomlar saqlangan — fayl o'qiladigan holda qolgan. Minifikatsiya yo'q.

  2. Network'da JS fayllari — 19 ta: turlar.js so'ralmaydi (build'dan keyin u bo'sh modul). CSS bilan — 20 ta. Son farq qilsa, "Disable cache" ni yoqib qayta yuklang.

3-mashq (qiyin): O'lchov skripti

kurs/mashqlar/16/01-hajm/ papkasida ikki fayl yozing:

  • hajm.mjs — measureAssets(dir) funksiyasini eksport qiladi. U papkadagi (ichki papkalar bilan) hamma .js va .css faylni topadi, sw.js dan tashqari. Har fayl uchun xom hajmni va gzip hajmini hisoblaydi. Natija: { files: [{ name, raw, gzip }], total: { raw, gzip } }.
  • olcha.mjs — buyruq qatoridan papka oladi, har fayl va jamini chiqaradi.

Keyin node olcha.mjs <vazifalar>/dist bilan o'z v5 loyihangizni o'lchang.

Ishoralar:

  • readdirSync(dir, { recursive: true }) — ichki papkalar bilan hamma nomni qaytaradi. Windows'da yo'l \ bilan keladi — replaceAll("\\", "/") bilan tekislang.
  • gzipSync(bytes, { level: 9 }) — node:zlib modulidan: baytlarni gzip bilan siqadi va siqilgan baytlarni qaytaradi. level: 9 — eng kuchli siqish. .length — siqilgan hajm.
  • process.argv[2] — buyruq qatoridagi birinchi argument (15-qismdagi skriptlardan tanish).
  • Funksiyani node:test bilan sinang: vaqtinchalik papka yasab (mkdtempSync), ichiga ma'lum hajmli fayllar yozing.
Yechim

hajm.mjs:

js
// hajm.mjs — papkadagi .js va .css fayllar hajmi: xom va gzip
import { readdirSync, readFileSync, statSync } from "node:fs";
import { join } from "node:path";
import { gzipSync } from "node:zlib";

// sw.js sahifa bilan birga yuklanmaydi — hisobga olmaymiz
export function measureAssets(dir) {
  const names = readdirSync(dir, { recursive: true })
    .map((name) => name.replaceAll("\\", "/"))
    .filter((name) => /\.(js|css)$/.test(name) && name !== "sw.js")
    .filter((name) => statSync(join(dir, name)).isFile())
    .sort();

  const files = names.map((name) => {
    const bytes = readFileSync(join(dir, name));
    const gzip = gzipSync(bytes, { level: 9 }).length;
    return { name, raw: bytes.length, gzip };
  });

  const total = { raw: 0, gzip: 0 };
  for (const file of files) {
    total.raw += file.raw;
    total.gzip += file.gzip;
  }
  return { files, total };
}

olcha.mjs:

js
// olcha.mjs — ishlatish: node olcha.mjs <papka>
import { measureAssets } from "./hajm.mjs";

const dir = process.argv[2];
if (!dir) {
  console.error("Papka bering: node olcha.mjs ../vazifalar/dist");
  process.exit(1);
}

const { files, total } = measureAssets(dir);
for (const file of files) {
  const raw = String(file.raw).padStart(7);
  const gzip = String(file.gzip).padStart(7);
  console.log(`${file.name.padEnd(32)}${raw}${gzip}`);
}
const kb = (bytes) => (bytes / 1000).toFixed(1);
console.log(
  `JAMI: ${files.length} fayl, ${kb(total.raw)} KB, ` +
    `gzip ${kb(total.gzip)} KB`,
);

statSync(…).isFile() — papka nomlarini (assets/js kabi) tashlab yuboradi: readdirSync ularni ham qaytaradi. .sort() — chiqish har kompyuterda bir xil tartibda bo'lsin.

Bizning v5 dist/ da (boshi va oxiri):

text
assets/css/vazifalar.css           4734   1661
assets/js/api.js                   4507   1757
assets/js/asosiy.js               20686   6454
…
assets/js/vazifa.js                1301    570
assets/js/vendor/web-vitals.js     9027   3376
JAMI: 21 fayl, 85.8 KB, gzip 32.0 KB

Darsdagi 85.8 va 32.0 KB aynan shu. Eng katta modul — asosiy.js (20.7 KB), ikkinchisi — render.js (12.6 KB). Sizning raqamlaringiz kodingizga qarab biroz farq qiladi. Bu skriptni saqlab qo'ying: Bundler nima darsida uni v6 dist/ ga ham ishlatasiz va JAMI: 4 fayl, 38.1 KB, gzip 14.3 KB ni o'z ko'zingiz bilan ko'rasiz.

Test (hajm.test.mjs) — node --test hajm.test.mjs:

js
// hajm.test.mjs — node --test hajm.test.mjs
import { test } from "node:test";
import assert from "node:assert/strict";
import {
  mkdtempSync,
  mkdirSync,
  writeFileSync,
  rmSync,
} from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { measureAssets } from "./hajm.mjs";

test("faqat .js va .css; sw.js va boshqalar sanalmaydi", () => {
  const dir = mkdtempSync(join(tmpdir(), "hajm-"));
  mkdirSync(join(dir, "assets"));
  writeFileSync(join(dir, "assets", "app.js"), "a".repeat(1000));
  writeFileSync(join(dir, "assets", "app.css"), "b{}");
  writeFileSync(join(dir, "sw.js"), "c".repeat(500));
  writeFileSync(join(dir, "index.html"), "<p>salom</p>");

  const { files, total } = measureAssets(dir);
  rmSync(dir, { recursive: true });

  assert.deepEqual(
    files.map((file) => file.name),
    ["assets/app.css", "assets/app.js"],
  );
  assert.equal(total.raw, 1003);
  // 1000 ta bir xil harf gzip'da juda qisqaradi
  assert.ok(files[1].gzip < 50);
});
text
ℹ tests 2
ℹ pass 2
ℹ fail 0

(Ikkinchi test — bo'sh papka uchun nol. Uni o'zingiz yozing.) kurs/mashqlar papkasidan:

bash
git add 16/01-hajm
git commit -m "16/01: hajm.mjs — dist/ dagi JS va CSS o'lchovi"

9. Real ishda

  • Vakansiyalarda shu zanjir so'raladi: "Vite", "webpack", "npm/pnpm", "ESLint", "CI/CD". Ishdagi birinchi haftangizda package.json dagi scripts va ildizdagi config fayllarni o'qiysiz — 16-qism shunga tayyorlaydi.
  • React loyihasi (17-qism) aynan shu zanjir bilan yaratiladi: npm create vite@latest. Next.js'ning (23-qism) zanjiri boshqa, lekin halqalar o'sha.
  • Intervyu savollari: "Bundler nima va nega kerak?", "Dev va build farqi?", "Fayl nomidagi hash nima uchun?", "Nega node_modules git'ga qo'shilmaydi?".

Xulosa

  • Brauzer faqat oddiy JavaScript, CSS va HTML'ni bajaradi: .ts — MIME yoki sintaksis xatosi, .jsx — Unexpected token '<'.
  • Asboblar zanjiri: paket menejeri → tekshiruvchilar → transpiler → bundler → minifikator va hash → deploy va CDN. Vositalarning hammasi Node'da ishlaydi.
  • Dev server fayllarni so'ralganda o'giradi (tez, HMR bilan), build esa bir marta to'liq yig'ib dist/ ga yozadi.
  • src/ — siz yozasiz va git'ga kiradi; node_modules/ va dist/ — buyruq yasaydi, git'ga kirmaydi.
  • vazifalar 16-qismda v5 → v6: JS + CSS 85.8 → 38.1 KB, gzip 32.0 → 14.3 KB, fayllar 20 → 4 — narxi node_modules 86 → 168 MB.

Keyingi dars: Node versiya menejerlari: nvm, fnm, Volta va .nvmrc — zanjirning birinchi halqasi: hamma dasturchi va CI bir xil Node versiyasida ishlashi uchun vazifalar ga .nvmrc va engines qo'shamiz.

Manbalar

  • Vite hujjatlari: "Why Vite", "Building for Production" — vite.dev/guide/
  • Rolldown — rolldown.rs; Oxc — oxc.rs
  • MDN: "MIME types", "JavaScript modules" (modul skriptlari va CORS) — developer.mozilla.org
  • GitHub Docs: "About GitHub Pages" — docs.github.com/pages
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Frontend asboblar zanjiri: manba koddan brauzergacha — IlmHamroh