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

Vite V: production build va bundle tahlili

Qisqacha: vite build har chunk uchun xom va gzip hajmini chiqaradi — bu sayt narxining birinchi o'lchovi. 500 kB dan katta chunk'da Vite ogohlantiradi. Chunk'larni bo'lishning ikki yo'li bor: dinamik import() (kod kerak bo'lgandagina yuklanadi) va build.rolldownOptions.output.codeSplitting (masalan, node_modules — alohida vendor chunk). "Qaysi modul qancha joy egallaydi?" savoliga rollup-plugin-visualizer javob beradi. Kutubxona qo'shishdan oldin narxini o'lchang: «Bahor»da Zod +23.71 KB gzip berdi va kanonga kirmadi.

Bu darsda

  • vite build chiqishidagi har ustunni o'qiysiz va dist/ tuzilmasini tushuntira olasiz.
  • Katta chunk ogohlantirishini va uning sabablarini bilasiz.
  • Kodni dinamik import() va codeSplitting guruhlari bilan bo'lasiz.
  • npm run analiz bilan bundle tarkibini ko'rasiz va kutubxona narxini o'lchab qaror qilasiz.
  • Library mode bilan o'z kichik kutubxonangizni yig'asiz.

Oldin bilishingiz kerak: Code splitting va hash bilan keshlash, Vite III: env va rejimlar, Tree shaking va minifikatsiya, Zod va turni sxemadan chiqarish.

1. Nega bu kerak?

Zod darsida bitta qaror qoldirgan edik: "vazifalar da Zod yo'q — bundler'siz u 233.7 KB. 16-qismda bundler bilan qayta ko'ramiz". Endi bundler bor. Jasur aka so'rayapti: "Zod endi kichrayadimi? Qo'shamizmi?"

Sardor "ha, tree shaking hammasini kesadi" demoqchi edi. Lekin to'g'ri javob — "o'lchab ko'raylik". Kutubxona qo'shish — narxi bor qaror: har foydalanuvchi uni har tashrifda yuklab oladi, sekin mobil internetda ham. Narxni bilmay qaror qilish — narxni ko'rmay bozordan xarid qilish kabi.

Bu darsda o'lchash asboblarini o'rganamiz: build chiqishini o'qish, chunk'larni bo'lish va bundle tarkibini "rentgen" qilish. vazifalar ga npm run analiz buyrug'ini qo'shamiz va Zod savoliga raqamlar bilan javob beramiz.

2. Build chiqishini o'qish

2.1 Har qator nima deydi

vazifalar ning hozirgi build chiqishi (Vite IV dan keyin, ranglarsiz):

text
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-Dvsf2Sj6.js   25.37 kB │ gzip: 9.51 kB │ map: 115.33 kB
✓ built in 171ms

Build uch bosqichdan o'tadi va har birini aytadi:

  • transforming... → ✓ 23 modules transformed — har modul o'girildi (TS → JS). 23 — import grafidagi modullar soni.
  • rendering chunks... — modullar chunk'larga yig'ildi va minifikatsiya qilindi.
  • computing gzip size... — har fayl uchun gzip hajmi hisoblandi (faqat ko'rsatish uchun: dist/ ga .gz fayl yozilmaydi).

Jadvalning ustunlari:

Ustun Ma'nosi
dist/assets/index-Dvsf2Sj6.js fayl va uning hash'i
25.37 kB xom hajm (minifikatsiyadan keyin)
gzip: 9.51 kB siqilgan hajm — foydalanuvchi aslida shuni yuklaydi
map: 115.33 kB source map — faqat DevTools ochilganda

Fayllar hajm bo'yicha o'sib boradigan tartibda: eng kattasi pastda, ko'zingiz unga birinchi tushadi. kB — 1000 bayt (KiB emas).

2.2 dist/ ichida nima bor

Build chiqishi faqat Vite yasagan fayllarni ko'rsatadi. dist/ da esa ko'proq — jami 15 fayl:

text
dist/
├── index.html
├── sw.js                    ← public/ dan (VERSIYA va QOBIQ to'ldirilgan)
├── manifest.webmanifest     ← public/ dan
└── assets/
    ├── index-Dvsf2Sj6.js  (+ .map)
    ├── index-BI1hyTgJ.css
    ├── olchov-G4bloHwN.js (+ .map)
    ├── js/tema.js         (+ .map)
    └── ikonlar/           ← public/ dan, 5 ta rasm

Uch xil kelib chiqish: Vite yig'gan va hash'lagan fayllar (index-…, olchov-…), nomi qat'iy qilingan kirish (tema.js) va public/ dan o'zgarishsiz ko'chganlar. Service Worker fayli sw.js ham public/ dan keladi, lekin build oxirida bizning skriptimiz uning ichiga fayllar ro'yxatini yozadi — buni keyingi darsda Vite plaginiga aylantiramiz. Qaysi brauzerlar uchun yig'ilgani — build.target (Polyfill va Baseline); u vite.config.ts da, build chiqishida ko'rinmaydi.

2.3 Qaysi raqamga qarash kerak

Sayt tezligi uchun asosiy raqam — gzip: server fayllarni siqib yuboradi (Frontend asboblar zanjiri), tarmoqdan shu hajm o'tadi. Lekin xom hajm ham muhim: brauzer JavaScript'ni ochgandan keyin xom matnni o'qiydi va bajaradi. Telefon protsessori uchun 100 kB JS — gzip 30 kB bo'lsa ham — 100 kB ish.

vazifalar da brauzer yuklaydigan JS + CSS (gzip, -9), Bundler nima dagi o'lchov skripti bilan:

Fayllar Xom gzip
15-qism oxiri (tsc, bundler'siz) 20 (diskda 21) 85 829 B 31 992 B
hozir (Vite) 4 38 058 B 14 275 B

Bu −56 % gzip va 20 so'rov o'rniga 4. Endi savol: shu 14 KB ichida nima bor?

Tekshirib ko'ring: Nega jadvalda dist/index.html bor, lekin uning hajmi "brauzer yuklaydigan JS + CSS" hisobiga kirmagan?

Javob

index.html — sahifaning o'zi, u har holda yuklanadi va bundler qarorlariga deyarli bog'liq emas. O'lchovimiz "bundler qancha JS va CSS beradi" degan savolga javob beradi, shuning uchun faqat .js va .css sanaladi (Service Worker sw.js siz — u sahifa bilan birga yuklanmaydi). O'lchovda nimani sanayotganingizni aniq aytish — halol taqqoslashning sharti.

3. Katta chunk va uni bo'lish

3.1 Ogohlantirish

Sardor bahor-menyu ga buyurtmani tekshirish uchun Zod qo'shdi (src/buyurtma.ts, 2 maydonli sxema) va build qildi:

text
✓ 102 modules transformed.
dist/index.html                  0.43 kB │ gzip:  0.28 kB
dist/assets/index-lc8mfrVt.css   0.07 kB │ gzip:  0.09 kB
dist/assets/index-B4vuCTRD.js   84.13 kB │ gzip: 24.20 kB

6 ta modul 102 taga aylandi — 96 tasi Zod'ning ichki fayllari. Ilova JS'i 1 kB dan 84 kB ga sakradi. Vite jim: sukut chegarasi 500 kB. Chegarani build.chunkSizeWarningLimit: 50 qilsak:

text
(!) Some chunks are larger than 50 kB after minification. Consider:
- Using dynamic import() to code-split the application
- Use build.rolldownOptions.output.codeSplitting to improve chunking: https://rolldown.rs/reference/OutputOptions.codeSplitting
- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.

Tarjimasi: "Ba'zi chunk'lar minifikatsiyadan keyin 50 kB dan katta. O'ylab ko'ring: dinamik import() bilan bo'lish; codeSplitting bilan chunk'larni sozlash; ogohlantirish chegarasini o'zgartirish". Uchta maslahat — uch yo'l. Uchinchisi (chegarani ko'tarish) — muammoni yashirish, yechim emas. Qolgan ikkitasini ko'ramiz. Katta chunk ko'rganda o'zingizga beradigan savollar tartibi:

flowchart TB
  A["katta chunk<br/>(build chiqishida)"] --> B{"npm run analiz:<br/>ichida nima?"}
  B --> C{"bu kod sahifa<br/>ochilishida kerakmi?"}
  C -->|yo'q| D["dinamik import()<br/>— keyinga surish"]
  C -->|ha| E{"kutubxonami?"}
  E -->|ha| F["vendor chunk<br/>— uzoq kesh"]
  E -->|yo'q| G["o'z kodingizni<br/>soddalashtiring"]
  B --> H{"kutubxona umuman<br/>kerakmi?"}
  H -->|yo'q| I["olib tashlang yoki<br/>arzonrog'ini o'lchang"]

3.2 Dinamik import() — kerak bo'lganda yuklash

Menyuni ko'rish uchun Zod kerak emas — faqat buyurtma berilganda. Statik importni dinamik import() ga almashtiramiz:

ts
// Zod faqat buyurtma berilganda kerak — alohida chunk
document.querySelector("h1")!.addEventListener("click", async () => {
  const { parseOrder } = await import("./buyurtma.ts");
  console.log(parseOrder({ dish: "Osh", count: 2 }).success);
});
text
dist/assets/index-BiDg9vXc.js      2.58 kB │ gzip:  1.25 kB
dist/assets/buyurtma-mz8PUfCS.js  83.12 kB │ gzip: 23.70 kB

Sahifa ochilganda faqat 2.58 kB yuklanadi. Zod 83 kB lik alohida chunk'da, birinchi bosishda keladi. Kod hajmi kamaymadi — u keyinga surildi. vazifalar dagi olchov chunk'i (web-vitals) xuddi shunday ajratilgan (Code splitting).

3.3 codeSplitting — vendor chunk

Ikkinchi yo'l: hamma kod darhol kerak, lekin kutubxonalarni alohida faylga ajratish. Nega? Ilova kodi har kuni o'zgaradi, kutubxona — oyda bir. Alohida faylda kutubxona brauzer keshida uzoq yashaydi. Vite 8 da bu Rolldown sozlamasi:

ts
export default defineConfig({
  build: {
    rolldownOptions: {
      output: {
        codeSplitting: {
          groups: [{ name: "vendor", test: /node_modules/ }],
        },
      },
    },
  },
});

groups — guruhlar ro'yxati: test ga mos kelgan modullar (yo'lida node_modules bor) name nomli chunk'ka tushadi. Natija:

text
dist/index.html                  0.50 kB │ gzip:  0.30 kB
dist/assets/index-lc8mfrVt.css   0.07 kB │ gzip:  0.09 kB
dist/assets/index-D_uOcO-w.js    1.17 kB │ gzip:  0.65 kB
dist/assets/vendor-CuDna4Mk.js  83.03 kB │ gzip: 23.66 kB

index.html ga Vite o'zi yangi qator qo'shdi: <link rel="modulepreload" crossorigin href="/assets/vendor-CuDna4Mk.js"> — brauzer ikkala faylni parallel yuklaydi.

Nomlar haqida: Rollup va eski Vite'da bu ish manualChunks bilan qilingan, Rolldown'ning birinchi versiyalarida — advancedChunks. Rolldown 1.2.12 ning tur faylida ikkalasi @deprecated ("eskirgan, codeSplitting ni ishlating"). Internetdagi maqolalarda uchala nomni ham ko'rasiz — ma'nosi bir.

Ehtiyot bo'ling: bo'lish har doim ham foyda emas. vazifalar da eng kichik fayl.ts modulini (629 bayt) alohida chunk qilish o'lchandi va qilinmadi: alohida so'rov uning o'zidan qimmat (Code splitting darsidagi o'lchov).

Tekshirib ko'ring: vendor chunk ajratildi, lekin sahifa ochilganda baribir ikkala fayl yuklanadi. Unda foyda nimada?

Javob

Birinchi tashrifda — deyarli yo'q (hatto bitta qo'shimcha so'rov). Foyda keyingi tashriflarda: siz ilova kodini o'zgartirib deploy qilsangiz, faqat index-….js ning hash'i o'zgaradi. vendor-CuDna4Mk.js o'sha-o'sha — brauzer uni keshdan oladi, 23.66 kB qayta yuklanmaydi. Kutubxona yangilanmaguncha shunday.

4. Bundle tahlili: rollup-plugin-visualizer

4.1 Rentgen

Build chiqishi faqat chunk hajmini aytadi. Chunk ichida qaysi modul qancha joy egallashi ko'rinmaydi. Buning uchun bundle analizator kerak. Eng mashhuri — rollup-plugin-visualizer (2026-10 holatiga 7.1.1). Nomida "rollup" bor, lekin Rolldown bilan ham ishlaydi — u plagin hook'lari orqali modullar ro'yxatini oladi (hook'lar — Vite plaginlari darsida).

U ikki ko'rinish beradi:

  • treemap — HTML sahifa: har to'rtburchak — bitta modul, maydoni — hajmi. Katta to'rtburchak darhol ko'zga tashlanadi.
  • markdown — matn jadvali: terminalda va PR izohida o'qish uchun.

4.2 Vazifalar qadami: npm run analiz

Branch: chore/analiz

bash
git switch -c chore/analiz
npm i -D rollup-plugin-visualizer@7.1.1

.npmrc dagi save-exact=true (Ta'minot zanjiri dan) tufayli package.json ga aniq "7.1.1" yoziladi. Yangi fayl skriptlar/analiz.js:

js
// skriptlar/analiz.js — bundle tahlili (16/#30): npm run analiz.
// Odatdagi build (vite.config.ts) + rollup-plugin-visualizer: qaysi
// modul har chunk'da qancha joy egallaydi. Natija — analiz/
// papkasida (dist/ ga tushmaydi: saytga ham, Service Worker
// keshiga ham kerak emas)
import { build } from "vite";
import { visualizer } from "rollup-plugin-visualizer";

await build({
  logLevel: "warn",
  build: { outDir: "analiz/dist", emptyOutDir: true },
  plugins: [
    // treemap — har to'rtburchak bitta modul, maydoni — hajmi
    visualizer({
      filename: "analiz/treemap.html",
      template: "treemap",
      gzipSize: true,
    }),
    // Matn ko'rinishi — terminalda va PR'da o'qish uchun
    visualizer({
      filename: "analiz/royxat.md",
      template: "markdown",
      gzipSize: true,
    }),
  ],
});
console.log("analiz/treemap.html, analiz/royxat.md");

Qatorma-qator:

  • import { build } from "vite" — Vite'ni buyruq qatorisiz, JavaScript'dan ishga tushirish (Vite'ning JavaScript API'si). build() odatdagi vite.config.ts ni o'qiydi va bizning sozlamalarimizni uning ustiga qo'shadi.
  • outDir: "analiz/dist" — tahlil build'i haqiqiy dist/ ni buzmasin. Service Worker qobig'iga ham tushmasin: dist/ dagi har fayl oflayn keshga kiradi, 200 KB lik treemap esa saytga kerak emas.
  • plugins: [visualizer(...), visualizer(...)] — bitta plagin ikki marta, ikki xil formatda. gzipSize: true — gzip hajmini ham hisoblash.
  • await — fayl boshida, funksiyasiz: top-level await (Dinamik import), .js fayl ESM bo'lgani uchun ("type": "module") ishlaydi.

Nega plaginni vite.config.ts ga emas, alohida skriptga qo'ydik? Har build'da tahlil kerak emas — u build'ni sekinlashtiradi va 200 KB lik HTML yozadi. Analiz — so'raganda.

package.json ga skript:

json
{
  "scripts": {
    "analiz": "node skriptlar/analiz.js"
  }
}

analiz/ — build natijasi, git'ga va tekshiruvlarga kirmasin. Uch joyga bir qatordan: .gitignore (analiz/), .prettierignore (analiz/), eslint.config.js (globalIgnores(["dist/", "analiz/"])).

4.3 Natija

bash
npm run analiz

analiz/royxat.md boshi (minifikatsiyadan oldingi hajmlar — Rendered):

text
| Bundles | Modules | Entries | Externals | Static Imports | Dynamic Imports |
| ---: | ---: | ---: | ---: | ---: | ---: |
| 3 | 22 | 2 | 0 | 30 | 1 |

| Metric | Total |
| --- | ---: |
| Rendered | 56.45 KiB |
| Gzip | 20.69 KiB |

## Top 10

- `src/asosiy.ts`: 20.8% (11.75 KiB)
- `node_modules/web-vitals/dist/web-vitals.js`: 20.0% (11.31 KiB)
- `src/render.ts`: 15.9% (8.97 KiB)
- `src/royxat.ts`: 5.9% (3.35 KiB)
- `src/paket.ts`: 5.2% (2.96 KiB)
- `src/api.ts`: 5.1% (2.89 KiB)
- ` vite/preload-helper.js`: 5.0% (2.81 KiB)

Nimani o'qiymiz:

  • 3 bundle (index, olchov, tema), 2 kirish nuqtasi (index.html va tema), 1 dinamik import (olchov).
  • Eng kattasi — o'z kodimiz asosiy.ts, ikkinchisi — web-vitals (u alohida chunk'da, sahifa ochilishiga xalaqit bermaydi).
  • vite/preload-helper.js — 2.81 KiB: Vite dinamik importlar uchun qo'shadigan yordamchi. Bizda bitta dinamik import uchun — sezilarli narx. Bu haqda o'ylab ko'rish mumkin, lekin 1.16 KiB gzip — kichik.
  • Dublikat (bir kutubxona ikki chunk'da) — yo'q.

Xulosa: bundle sog'lom. Hech bir begona kutubxona ilovani "yeb" qo'ymagan.

Tekshirish va commit: npm run check toza, npm run build — o'sha hash'lar (dist/ ga hech narsa qo'shilmadi), testlar 145/145, brauzer tekshiruvi 159/159.

bash
git add .
git commit -m \
"chore: npm run analiz — bundle tahlili (rollup-plugin-visualizer)"

Diff: 6 fayl, +470 −4 — deyarli hammasi package-lock.json (visualizer'ning bog'liqliklari).

5. Zod: o'lchab qaror qilish

5.1 Tajriba

15-qism va'dasi. paket.ts dagi vazifa tekshiruvi (id — butun son ≥ 1, matn — bo'sh emas va ≤ 100 belgi, bajarildi — boolean) har kutubxona sxemasi bilan almashtirildi, qolgan hamma narsa — o'zgarishsiz. To'rt variant, index chunk (Vite build chiqishidan):

Variant index chunk Farq (gzip)
qo'lda yozilgan (kanon) 25.38 kB │ gzip: 9.51 kB —
Valibot 1.5.0 29.89 kB │ gzip: 10.85 kB +1.34 KB (+14 %)
zod/mini 4.6.5 42.54 kB │ gzip: 15.03 kB +5.52 KB (+58 %)
Zod 4.6.5 109.06 kB │ gzip: 33.22 kB +23.71 KB (+249 %)
vazifalar index chunk: tekshiruv kutubxonasi narxi (gzip)
  • qo'lda (kanon)9,51 KB
  • Valibot 1.5.0+14 %10,85 KB
  • zod/mini 4.6.5+58 %15,03 KB
  • Zod 4.6.5+249 %33,22 KB

Manba: O'lchandi: vazifalar (16-qism), vite build 8.3.3, Node 24.21.0, 2026-10-07

Ustunlarga qarang: Zod butun ilovadan ham katta.

Valibot va zod/mini — Zod g'oyasidagi, lekin tree shaking uchun qurilgan kutubxonalar: har tekshiruv alohida funksiya (z.minLength(1)), shuning uchun ishlatilmaganlari kesiladi. Oddiy Zod'da esa metodlar (z.string().min(1)) bitta katta klassda — bundler ularni ajrata olmaydi. Tree shaking kodingiz qanday yozilganiga bog'liq (Tree shaking).

5.2 Hajmdan tashqari topilmalar

O'lchov faqat raqam bermadi:

  • Testlar (bu o'lchov qism oxiridagi 146 ta test bilan qilingan): har kutubxona bilan 2 tasi yiqildi. Sabab — xato xabari. Bizniki: "bajarildi true yoki false emas.", kutubxonaniki: Invalid type: Expected boolean…. O'zbekcha xabar uchun har maydonga alohida matn yozish kerak — sxema uzayadi.
  • Xavfsizlik: oddiy Zod sukut bo'yicha tezlik uchun new Function(...) bilan kod yasaydi. vazifalar ning CSP va Trusted Types himoyasi (XSS va DOM xavfsizligi) buni to'sdi. Brauzer tekshiruvida 159 dan 2 tasi yiqildi, konsolda 23 marta This document requires 'TrustedScript' assignment. Yechim bor (z.config({ jitless: true })), lekin buni o'lchamasdan bilmas edik.

15-qismda Zod bundler'siz 233.7 KB edi. Tree shaking va minifikatsiya uni 7 marta kichraytirdi — lekin u baribir ilovamizning butun JS'idan 2.5 baravar katta. Yana bir eslatma: biz import { z } from "zod" yozdik va Vite (Rolldown) uni to'g'ri kesdi. esbuild'da xuddi shu yozuv tillar (locale) xabarlarini ham tortib keladi — Paket tanlash darsida 90.6 KB edi. Raqam bundlerga ham bog'liq.

5.3 Qaror

Kanonda qo'lda yozilgan tekshiruv qoladi. Sabablar: uch maydonli sxema uchun eng arzon variant ham (+14 %) yangi bog'liqlik (Ta'minot zanjiri xavfi), uchinchi API va uzunroq sxema (o'zbekcha xabarlar uchun) qo'shadi. Qo'lda yozilgan funksiya allaqachon testlangan. Zod — 25-qismda serverda (u yerda hajm muhim emas); sxema frontend va backend uchun umumiy bo'lsa — qaror qayta ko'riladi.

Muhimi — qaror emas, usul: kutubxonani o'rnatishdan oldin uning narxini o'z loyihangizda o'lchang. Bir kun "kichik kutubxona" deb o'rnatilgan paket sayt hajmini ikki baravar oshirgan voqealar ko'p.

Tekshirib ko'ring: Hamkasbingiz aytdi: "Paket hajmini ko'rsatadigan saytda Zod biz o'lchagandan ancha katta chiqdi. Qaysi raqam to'g'ri?"

Javob

Ikkalasi ham o'z savoliga to'g'ri. Bunday saytlar kutubxonani odatda butunligicha o'lchaydi (go'yo hamma narsasi import qilingan). Bizning o'lchov — bizning kodimiz ishlatgan qismi, tree shaking'dan keyin. Qaror uchun ikkinchisi kerak — shuning uchun o'z loyihangizda o'lchaysiz.

6. Library mode: kutubxona yig'ish

Hozirgacha Vite ilova yig'di: index.html dan boshlab, brauzer uchun. Ba'zan esa kutubxona kerak — boshqa loyihalar npm i qilib import qiladigan kod. Masalan, «Bahor»ning formatPrice funksiyasi uch xil loyihada ishlatiladi. Buning uchun build.lib:

ts
// vite.lib.ts — kutubxona build'i
import { defineConfig } from "vite";

export default defineConfig({
  build: {
    outDir: "lib",
    lib: {
      entry: "src/menyu.ts",
      name: "BahorMenyu",
      formats: ["es", "umd"],
      fileName: "bahor-menyu",
    },
  },
});
bash
npx vite build --config vite.lib.ts
text
✓ 2 modules transformed.
lib/bahor-menyu.js  0.30 kB │ gzip: 0.22 kB

✓ 2 modules transformed.
lib/bahor-menyu.umd.cjs  0.47 kB │ gzip: 0.31 kB

✓ built in 103ms
  • entry — kirish nuqtasi index.html emas, .ts fayl. HTML yo'q.
  • formats — es (zamonaviy ESM, export { … }) va umd (eski usul: <script> bilan ham, require bilan ham ishlaydi; name — global o'zgaruvchi nomi). Formatlar — Modul formatlari darsida.
  • ES fayl minifikatsiya qilinmagan (//#region src/menyu.ts, bo'sh joylar bilan): kutubxonani oxirida ilova bundler'i siqadi, bu yerda o'qiladigan qolsin.

Lekin kutubxona uchun Vite — yagona yoki eng yaxshi tanlov emas. .d.ts turlarini ham chiqarish kerak, package.json dagi exports (kirish nuqtalari) ham. Bunga maxsus vositalar bor (tsdown) — Bundlerlar landshafti darsida.

Tekshirib ko'ring: bahor-menyu kutubxonasi zod ni import qilsa, library mode Zod'ni lib/bahor-menyu.js ichiga qo'shib yuboradimi? Bu yaxshimi?

Javob

Sukut bo'yicha — ha, bundler import grafidagi hamma narsani yig'adi. Kutubxona uchun bu yomon: ilova o'zi ham Zod ishlatsa, foydalanuvchi uni ikki marta yuklaydi (bir nusxa sizning kutubxonangiz ichida). Shuning uchun kutubxonalarda bog'liqliklar tashqi (external) qilinadi — rolldownOptions.external: ["zod"] — va package.json ning dependencies yoki peerDependencies ida yoziladi (Bog'liqlik turlari). Ularni ilovaning bundler'i bir marta qo'shadi.

7. Ko'p uchraydigan xatolar

7.1 Ogohlantirishni chegara bilan "tuzatish"

chunkSizeWarningLimit: 2000 — ogohlantirish yo'qoldi, sayt esa o'sha-o'sha og'ir. Avval tahlil: nima katta va u darhol kerakmi?

7.2 Hamma narsani bo'lib tashlash

Har modul — alohida chunk: 50 ta so'rov, har biri kichik. HTTP/2 bilan ham har so'rovning narxi bor. Bo'lish — o'lchov bilan, ko'r-ko'rona emas.

7.3 Tahlil natijasini dist/ ga yozish

visualizer({ filename: "dist/stats.html" }) — fayl saytga chiqadi va (vazifalar da) Service Worker keshiga kiradi. Tahlil — alohida papkada.

7.4 Butun kutubxonani import qilish

import _ from "lodash" — butun kutubxona. import { debounce } from "lodash-es" — faqat bitta funksiya (ESM versiyasida). Analizator buni darhol ko'rsatadi.

8. Mashqlar

Mashqlar kurs/mashqlar/16/30-bundle/ da — bahor-menyu nusxasi. npm i -E zod@4.6.5 va npm i -D -E rollup-plugin-visualizer@7.1.1.

1-mashq (oson): Chiqishni o'qing

Darsdagi vazifalar build chiqishidan javob bering:

  1. Foydalanuvchi eng ko'p yuklaydigan fayl va uning siqilgan hajmi — index-Dvsf2Sj6.js, kB.
  2. Nechta modul o'girildi — .
  3. Qaysi faylning nomida hash yo'q (index.html dan tashqari) — assets/js/.
  4. Source map'larning eng kattasi — kB.
Yechim
  1. 9.51 kB gzip (xom — 25.37 kB).
  2. 23.
  3. tema.js — u entryFileNames bilan ataylab hash'siz (Vite II).
  4. 115.33 kB — index chunk'ining xaritasi; u faqat DevTools ochilganda yuklanadi.

2-mashq (o'rta): Zod'ni keyinga suring

src/buyurtma.ts — darsdagi Zod sxemasi (dish — bo'sh bo'lmagan satr, count — musbat butun son) va parseOrder(data). main.ts uni <h1> bosilganda dinamik import qilsin. Build qiling: sahifa ochilganda qancha JS yuklanadi, Zod chunk'i qancha? Keyin npm run analiz (darsdagi analiz.js) bilan eng katta 3 modulni toping.

Yechim

src/buyurtma.ts:

ts
// buyurtma.ts — buyurtma ma'lumotini Zod bilan tekshirish
import { z } from "zod";

const Order = z.object({
  dish: z.string().min(1),
  count: z.number().int().positive(),
});

export function parseOrder(data: unknown) {
  return Order.safeParse(data);
}

main.ts — darsdagi addEventListener("click", async () => { … await import("./buyurtma.ts") … }). Build:

text
dist/assets/index-BiDg9vXc.js      2.58 kB │ gzip:  1.25 kB
dist/assets/buyurtma-mz8PUfCS.js  83.12 kB │ gzip: 23.70 kB

Sahifa ochilganda — 1.25 kB gzip, Zod — 23.70 kB, faqat bosilganda. npm run analiz (royxat.md, yo'llar qisqartirildi):

text
| Rendered | 155.99 KiB |
| Gzip | 38.60 KiB |
- `…/node_modules/zod/v4/core/schemas.js`: 25.3% (38.69 KiB)
- `…/node_modules/zod/v4/classic/schemas.js`: 14.7% (22.50 KiB)
- `…/node_modules/zod/v4/core/to-json-schema.js`: 9.9% (15.20 KiB)

Qiziq topilma: to-json-schema.js — Zod sxemasini JSON Schema'ga o'giradigan qism. Biz uni ishlatmadik, lekin u bundle'da: oddiy Zod API'sini tree shaking to'liq kesa olmaydi.

3-mashq (qiyin): Uch variantni o'lchang

buyurtma.ts ning uch varianti bilan build qiling va buyurtma-….js chunk hajmini jadvalga yozing: (1) Zod, (2) zod/mini, (3) kutubxonasiz, qo'lda. Har variantda npx tsc --noEmit toza bo'lsin. Qaysi birini tanlaysiz va nega?

Ishora: zod/mini da metodlar o'rniga funksiyalar: z.string().check(z.minLength(1)), z.number().check(z.int(), z.positive()); import — import * as z from "zod/mini". Qo'lda variantda typeof va Number.isInteger yetarli.

Yechim

zod/mini:

ts
// buyurtma.ts — buyurtma ma'lumotini zod/mini bilan tekshirish
import * as z from "zod/mini";

const Order = z.object({
  dish: z.string().check(z.minLength(1)),
  count: z.number().check(z.int(), z.positive()),
});

export function parseOrder(data: unknown) {
  return Order.safeParse(data);
}

Qo'lda:

ts
// buyurtma.ts — qo'lda yozilgan tekshiruv (kutubxonasiz)
export function parseOrder(data: unknown) {
  if (typeof data !== "object" || data === null) {
    return { success: false as const, error: "obyekt emas" };
  }
  const { dish, count } = data as Record<string, unknown>;
  if (typeof dish !== "string" || dish.length === 0) {
    return { success: false as const, error: "dish bo'sh" };
  }
  if (typeof count !== "number" || !Number.isInteger(count)) {
    return { success: false as const, error: "count butun emas" };
  }
  if (count <= 0) {
    return { success: false as const, error: "count musbat emas" };
  }
  return { success: true as const, data: { dish, count } };
}

Natija (buyurtma chunk'i):

Variant Xom gzip
Zod 4.6.5 83.12 kB 23.70 kB
zod/mini 4.6.5 15.56 kB 5.35 kB
qo'lda 0.35 kB 0.22 kB

Ikki maydon uchun — qo'lda: 100 baravar kichik va xabarlar o'zimizniki. Ko'p sxemali, murakkab formalarda (o'nlab maydon, ichma-ich obyektlar) — zod/mini yoki Valibot o'zini oqlaydi: qo'lda yozilgan kod ham o'sadi va xato qilish oson bo'ladi. Javobingizdagi asos — raqam va loyiha hajmi bo'lsa, u to'g'ri.

9. Real ishda

  • PR'da bundle hajmi — katta jamoalarda CI har PR'da build qilib, "bu o'zgarish JS'ni +12 KB oshirdi" deb izoh yozadi (size-limit kabi vositalar). Chegaradan oshsa — PR to'xtaydi.
  • Kutubxona tanlash (Paket tanlash) — hajm har doim mezonlardan biri; o'lchov esa o'z loyihangizda.
  • Intervyu savollari: "Bundle hajmini qanday kamaytirasiz?", "vendor chunk nima uchun?", "Dinamik import qachon foydali?".

Xulosa

  • Build chiqishi: har chunk — xom va gzip hajm; tarmoq uchun gzip, telefon protsessori uchun xom hajm muhim.
  • 500 kB (sozlanadi) dan katta chunk'da ogohlantirish; chegarani ko'tarish — yechim emas.
  • Bo'lishning ikki yo'li: dinamik import() (keyinga surish) va codeSplitting.groups (vendor — kesh uchun). manualChunks/advancedChunks — eski nomlar.
  • rollup-plugin-visualizer — chunk ichidagi modullar; vazifalar da npm run analiz → analiz/ (git, Prettier, ESLint'dan tashqarida).
  • Zod +23.71 KB gzip, zod/mini +5.52, Valibot +1.34 — vazifalar da qo'lda yozilgan tekshiruv qoldi. Kutubxonani o'lchab qo'shing.
  • build.lib — kutubxona yig'ish (ES va UMD); to'liq kutubxona uchun maxsus vositalar bor.

Keyingi dars: Vite plaginlari va o'z plaginingizni yozish — plagin hook'lari va vazifalar ning Service Worker qobig'ini postbuild skriptidan Vite plaginiga ko'chiramiz.

Manbalar

  • Vite hujjatlari: "Building for Production", "Library Mode", build.chunkSizeWarningLimit — vite.dev/guide/build
  • Rolldown: output.codeSplitting — rolldown.rs/reference/OutputOptions.codeSplitting
  • rollup-plugin-visualizer 7.1.1 — npmjs.com/package/rollup-plugin-visualizer
  • vazifalar o'lchovlari: Vite 8.3.3, zod 4.6.5, valibot 1.5.0, Node 24.21.0, 2026-10-07
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Vite V: production build va bundle tahlili — IlmHamroh