Mundarija (27)
- Bu darsda
- 1. Nega bu kerak?
- 2. Kichik loyiha: «Bahor» menyusi
- 2.1 Fayllar
- 2.2 Bog'liqlik grafi
- 3. Build: graf qanday fayllarga aylanadi
- 3.1 Birinchi vite build
- 3.2 Chunk
- 3.3 O'lik kod
- 3.4 Asset va output
- 4. Plagin va loader
- 5. Dev va production
- 6. vazifalar ning grafi
- 6.1 Ogohlantirish: can't be bundled
- 6.2 Raqamlar
- 7. Ko'p uchraydigan xatolar
- 7.1 public/ siz: manifest buzildi
- 7.2 Yashil test aldaydi: blocking="render"
- 7.3 dist/ ni file:// bilan ochish
- 8. Mashqlar
- 1-mashq (oson): Atamani toping
- 2-mashq (o'rta): Kichik loyihani yig'ing
- 3-mashq (qiyin): Grafni ko'rsatadigan plagin
- 4-mashq: Vazifalar qadami — vite build
- 9. Real ishda
- Xulosa
- Manbalar
Bundler nima: bog'liqlik grafi, entry, chunk va asset
Qisqacha: Bundler (yig'uvchi) kirish faylidan (entry) boshlab hamma
importlarni kuzatadi va bog'liqlik grafini quradi. Keyin graf tugunlarini (modullarni) bir necha chunk ga (yig'ilgan JS fayllarga) birlashtiradi, rasm, CSS va shriftlarni esa asset sifatida nomiga hash qo'shib chiqaradi. Dinamikimport()alohida chunk yaratadi, ishlatilmagan kod tashlanadi. Bugunvazifalargavite buildqo'shamiz: 20 ta so'rov o'rniga 4 ta, gzip bilan 32.0 KB o'rniga 14.4 KB.
Bu darsda
- Entry, bog'liqlik grafi, modul, chunk, asset va output atamalarini haqiqiy build chiqishida ko'rsata olasiz.
- Kichik loyihani
vite buildbilan yig'ib, har chunk ichida qaysi modullar borligini o'z plaginingiz bilan chiqarasiz. - Dev server va production build bir xil kodni qanday turlicha berishini ko'rasiz.
vazifalarnitsc+ nusxalashdanvite buildga o'tkazasiz vapublic/papkasi nega kerakligini bilasiz.
Oldin bilishingiz kerak: Frontend asboblar zanjiri, Modul formatlari, Dinamik import va top-level await, TypeScript build: tsc, bundler'lar va tsgo.
1. Nega bu kerak?
Asboblar zanjiri darsida vazifalar v5 ning dist/ ini o'lchagan edik. Unda 21 ta JavaScript va CSS fayl bor, brauzer ulardan 20 tasini alohida so'raydi. web-vitals paketini esa qo'lda vendor/ papkasiga ko'chirgan edik, chunki brauzer import "web-vitals" ni qayerdan izlashni bilmaydi.
tsc va bundler'lar darsida esa esbuild'ni fayl-fayl ishlatib ko'rdik va tuzoqqa tushdik: import "./royxat.ts" yo'li o'zgarmay qoldi. O'shanda va'da berdik: bundler bu muammoni ildizidan yechadi, chunki unda "yo'l" umuman qolmaydi — modullar bitta faylga kiradi.
Bugun shu va'dani bajaramiz. Hayotiy o'xshatish: «Bahor» oshxonasiga 15 ta yetkazib beruvchidan mahsulot keladi — har biri alohida mashinada, alohida vaqtda. Bundler — omborchi: ertalab hammasini bir joyga yig'ib, oshpazga bitta tayyor savat beradi. Kam qatnov, kam kutish.
Maslahat: Chiqishlar 2026-10-10 da Windows 11, Node 24.21.0 va Vite 8.3.3 bilan olingan. Ranglar olib tashlangan. Fayl nomlaridagi hash (
index-ys8EmKCO.js) va vaqtlar (built in 114ms) sizda boshqacha bo'ladi.
2. Kichik loyiha: «Bahor» menyusi
2.1 Fayllar
Tushunchalarni avval kichik, sof JavaScript loyihada ko'ramiz. vazifalar dagi 24 modul — keyin. Papka tuzilmasi:
menyu/
├── index.html
├── package.json "type": "module", vite 8.3.3
└── src/
├── main.js kirish nuqtasi
├── dishes.js taomlar ro'yxati
├── price.js narxni yozish
├── report.js hisobot — tugma bosilganda
├── menyu.css
└── logo.svgindex.html da faqat ikki ulanish:
<link rel="stylesheet" href="/src/menyu.css">
<script type="module" src="/src/main.js"></script>main.js:
// main.js — kirish nuqtasi (entry)
import { dishes } from "./dishes.js";
import { formatPrice } from "./price.js";
import logoUrl from "./logo.svg";
const list = document.querySelector("#menyu");
for (const dish of dishes) {
const item = document.createElement("li");
item.textContent = `${dish.name} — ${formatPrice(dish.price)}`;
list.append(item);
}
document.title += ` (${logoUrl})`;
// Hisobot kerak bo'lgandagina yuklanadi — alohida chunk
const button = document.querySelector("#hisobot");
button.addEventListener("click", async () => {
const { buildReport } = await import("./report.js");
console.log(buildReport(dishes));
});Uchinchi qatorga e'tibor bering: import logoUrl from "./logo.svg" — JavaScript'da rasm import qilinmoqda! Brauzer buni tushunmaydi, lekin bundler tushunadi: u rasmni alohida faylga chiqarib, logoUrl ga uning manzilini beradi.
price.js da ikki funksiya, ulardan biri hech qayerda ishlatilmaydi:
// price.js — narxni chiroyli yozish
export function formatPrice(sum) {
return `${String(sum).replace(/\B(?=(\d{3})+$)/g, " ")} so'm`;
}
// Hech qayerda ishlatilmaydi — build'ga tushmasligi kerak
export function formatDollar(sum) {
return `$${(sum / 12800).toFixed(2)}`;
}
console.log(formatPrice(35000)); // 35 000 so'm(Oxirgi qator faqat shu darsda natijani ko'rsatish uchun; loyihadagi faylda u yo'q.) report.js ham formatPrice ni import qiladi va jami narxni hisoblaydi.
2.2 Bog'liqlik grafi
Bundler index.html dan boshlaydi va har import ni o'q sifatida chizadi:
flowchart TB
H["index.html"] --> M["main.js<br/>(entry)"]
H --> C["menyu.css"]
M --> D["dishes.js"]
M --> P["price.js"]
M --> L["logo.svg"]
M -. "import()" .-> R["report.js"]
R --> PUzluksiz o'qlar — statik import, uzuq o'q — dinamik import(). price.js ga ikki yo'l keladi: main.js dan ham, report.js dan ham. Bu muhim — pastda ko'ramiz.
Atamalarni shu rasm bilan aniqlaymiz:
- Entry (kirish nuqtasi) — graf boshlanadigan fayl. Vite'da bu
index.html, undan keyin<script type="module">dagimain.js. Bitta loyihada bir nechta entry bo'lishi mumkin. - Modul — grafning bitta tuguni: JS, CSS, rasm — bundler uchun hammasi modul.
- Bog'liqlik grafi (dependency graph) — modullar va ular orasidagi
importlar xaritasi. Xuddi metro sxemasi: bekatlar — modullar, yo'llar — importlar.
3. Build: graf qanday fayllarga aylanadi
3.1 Birinchi vite build
Chiqishda ikki joyga qarang: modules transformed qatoridagi son (grafdagi modullar) va dist/ bilan boshlanadigan qatorlar (brauzerga boradigan fayllar).
npx vite build --assetsInlineLimit 0vite v8.3.3 building client environment for production...
transforming...
✓ 10 modules transformed.
rendering chunks...
computing gzip size...
dist/assets/logo-mWEg-Urw.svg 0.11 kB │ gzip: 0.12 kB
dist/index.html 0.38 kB │ gzip: 0.25 kB
dist/assets/index-CRKnUwHd.css 0.06 kB │ gzip: 0.08 kB
dist/assets/report-12McAH2s.js 0.15 kB │ gzip: 0.15 kB
dist/assets/index-ys8EmKCO.js 2.64 kB │ gzip: 1.30 kB
✓ built in 114msBosqichlar nomi bilan yozilgan:
| Qator | Bosqich | Nima bo'ldi |
|---|---|---|
transforming... |
o'girish | har modul o'qildi, kerak bo'lsa o'girildi |
10 modules transformed |
graf | grafda 10 ta modul |
rendering chunks... |
yig'ish | modullar chunk'larga birlashtirildi |
computing gzip size... |
o'lchash | siqilgan hajm hisoblandi |
--assetsInlineLimit 0 nima ekanini pastda, asset bo'limida ko'ramiz. 10 ta modul — bizning 6 ta faylimiz, index.html va Vite'ning o'zi qo'shgan yordamchilar.
3.2 Chunk
Chunk (bo'lak) — bir nechta modul birlashtirilgan bitta chiqish JS fayli. Bizda ikkita: index-….js va report-….js. Qaysi modul qaysi chunk'ga tushganini Vite chiqishda aytmaydi. Uni ko'rish uchun 10 qatorli o'z plaginimizni yozdik (to'liq kodi 3-mashqda):
chunk assets/index-ys8EmKCO.js (entry)
← vite/modulepreload-polyfill.js
← src/menyu.css
← src/dishes.js
← src/price.js
← src/logo.svg
← vite/preload-helper.js
← src/main.js
← index.html
chunk assets/report-12McAH2s.js (dinamik)
← src/report.js
asset assets/index-CRKnUwHd.css
asset assets/logo-mWEg-Urw.svgUchta qoida ko'rinib turibdi:
- Statik importlar — entry chunk'iga.
main.js,dishes.js,price.js— bitta faylda. - Dinamik
import()— alohida chunk.report.jsfaqat tugma bosilganda yuklanadi. Bu Dinamik import darsidagi g'oya: bundler uni avtomatik bo'lak qiladi. - Umumiy modul — bir marta.
price.jsikkala chunk'ga ham kerak, lekin u faqat entry chunk'ida.reportchunk'i uni o'sha yerdan oladi.
Uchinchi qoidani report chunk'ining ichida ko'rish mumkin:
import{t as e}from"./index-ys8EmKCO.js";function t(t){let n=t.reduce((e,t)=>e+t.price,0);return`Jami ${t.length} taom, ${e(n)}`}export{t as buildReport};formatPrice endi t deb nomlangan va index-ys8EmKCO.js dan import qilinmoqda — chunk'lar o'zaro ham modul. vite/preload-helper.js — Vite'ning dinamik import uchun yordamchisi, vite/modulepreload-polyfill.js — eski brauzerlar uchun yamoq (Polyfill va Baseline darsida uni o'chiramiz).
3.3 O'lik kod
formatDollar qayerda?
grep -c formatDollar dist/assets/*.jsdist/assets/index-ys8EmKCO.js:0
dist/assets/report-12McAH2s.js:0Hech qayerda — hatto 12800 raqami ham yo'q. Bundler grafni ko'rib bildi: formatDollar ni hech kim import qilmaydi. Bu tree shaking — Tree shaking va minifikatsiya darsining mavzusi.
3.4 Asset va output
Asset — JavaScript bo'lmagan chiqish fayli: CSS, rasm, shrift, video. Bundler uni nusxalaydi, nomiga hash qo'shadi va kodda unga havolani yangi nomga almashtiradi. logoUrl endi /assets/logo-mWEg-Urw.svg ga teng.
Kichik assetlar boshqacha ishlanadi. --assetsInlineLimit 0 siz build'da logo.svg fayli chiqmadi: u 4 KB dan kichik bo'lgani uchun Vite uni to'g'ridan-to'g'ri JS ichiga data: manzil qilib joyladi. Bitta kichik so'rov tejaldi. Chegarani build.assetsInlineLimit belgilaydi (sukut — 4096 bayt). Biz uni 0 qilib, asset'ni ko'rinadigan qildik.
Output (chiqish) — hamma natija yoziladigan papka, sukut bo'yicha dist/. Vite index.html ni ham qayta yozdi:
<script type="module" crossorigin
src="/assets/index-ys8EmKCO.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-CRKnUwHd.css">/src/main.js o'rniga — hash'li chunk, /src/menyu.css o'rniga — hash'li CSS. crossorigin atributi — modul skriptlar CORS bilan yuklanadi (Brauzerda ESM darsida).
Tekshirib ko'ring:
report.jshamdishes.jsni import qilsa,dishes.jsqaysi chunk'da bo'ladi — bitta yoki ikkala chunk'da?
Javob
Bitta — entry chunk'ida. U baribir sahifa ochilganda kerak (statik importda), shuning uchun u yerda bo'ladi; report chunk'i uni import qiladi. Bundler bir modulni ikki chunk'ga takrorlamaydi — aks holda u ikki marta yuklanib, ikki marta bajarilardi va modul semantikasi (bir marta bajarilish) buzilardi.
4. Plagin va loader
import logoUrl from "./logo.svg" qanday ishladi? JavaScript parser SVG'ni o'qiy olmaydi. Uni plagin o'qidi.
Plagin (plugin) — bundlerga yangi imkoniyat qo'shadigan kod bo'lagi. U build bosqichlariga hook (bosqichga ulanish nuqtasi) orqali ulanadi: resolveId (import yo'lini topish), load (faylni o'qish), transform (kodni o'zgartirish), generateBundle (chiqish fayllari tayyor bo'lganda). Vite'ning ichki plaginlari CSS, rasm, JSON, TypeScript'ni shunday ishlaydi. Biz yozgan "graf ko'rsatkich" ham generateBundle ga ulangan plagin.
Loader — webpack'dagi (eski, lekin hali keng tarqalgan bundler) shunga o'xshash tushuncha: ".svg fayllarini shu dastur o'qisin" (webpack konseptlari darsida). Vite'da loader yo'q — hammasi plagin.
Plaginlarni o'zimiz yozishni Vite plaginlari darsida chuqur o'rganamiz. Bugun vazifalar da bitta kichik plagin uchratamiz.
5. Dev va production
Asboblar zanjiri darsida dev server'ni oldindan ko'rgan edik. Endi aynan bir faylni ikki rejimda solishtiramiz. Dev server (npx vite) /src/main.js so'roviga shuni qaytardi (boshi):
// main.js — kirish nuqtasi (entry)
import { dishes } from "/src/dishes.js";
import { formatPrice } from "/src/price.js";
import logoUrl from "/src/logo.svg?import";Va /src/price.js so'roviga — formatDollar bilan birga to'liq fayl. Farqlar:
| Dev server | Production build | |
|---|---|---|
| Fayllar | har modul — alohida so'rov | bir necha chunk |
| Graf | so'ralganda, bo'lak-bo'lak | butunlay, oldindan |
| Importlar | /src/price.js ga qayta yozilgan |
chunk ichida yo'q bo'lib ketgan |
| Ishlatilmagan kod | bor (formatDollar) |
tashlangan |
| Izohlar, nomlar | saqlangan | minifikatsiya qilingan |
| Maqsad | tezkor ishga tushish, HMR | kichik va tez yuklanish |
Dev'da Vite bundle qilmaydi: brauzer ESM'ni o'zi tushunadi, Vite faqat yo'llarni to'g'rilaydi va kerak bo'lsa o'giradi. Shuning uchun katta loyihada ham dev server bir zumda ishga tushadi. Nega bunday ekanini Vite I darsida ochamiz. Muhim xulosa: dev'da ishlagani production'da ishlashini kafolatlamaydi — har o'zgarishdan keyin build ham qilinadi va natijasi tekshiriladi.
6. vazifalar ning grafi
Endi haqiqiy loyiha. Kanon build chiqishidan (tsc dan keyin). Birinchi qator — ogohlantirish, uni pastda ochamiz; qolganida yana modullar soni va dist/ qatorlariga qarang:
<script src="assets/js/tema.js"> in "/index.html" can't be bundled without type="module" attribute
✓ 24 modules transformed.
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.12 kB │ gzip: 0.12 kB
dist/assets/olchov-G4bloHwN.js 8.87 kB │ gzip: 3.38 kB
dist/assets/index-BewOu_Dy.js 25.86 kB │ gzip: 9.67 kB
✓ built in 217ms
sw.js: QOBIQ — 12 ta, VERSIYA — v6-3a23fab5Tanish atamalar bilan o'qiymiz:
- Entry —
index.html→asosiy.ts. Grafda 24 modul: bizning.tsmodullarimiz,web-vitals, Vite yordamchilari, CSS va HTML. - Ikki chunk.
index-….js— ilovaning hamma statik modullari bitta faylda.olchov-….js— Core Web Vitals o'lchovi dinamikimport("./olchov.ts")bilan yuklanadi vaweb-vitalspaketi aynan shu chunk'ga tushdi: sahifa ochilishida u umuman yuklanmaydi. - Asset —
index-….css. tema.js— alohida va hash'siz. Bu ataylab.
6.1 Ogohlantirish: can't be bundled
Asboblar zanjiri darsida bu qatorni keyinga qoldirgan edik. Tarjimasi: "index.html dagi <script src="assets/js/tema.js"> ni type="module" atributisiz yig'ib bo'lmaydi".
tema.js — oddiy (modul bo'lmagan) skript. U Qorong'i rejim va temalash darsidan beri <head> da sahifa chizilishidan oldin ishlaydi va qorong'i/yorug' temani qo'yadi — aks holda sahifa bir lahza oq bo'lib "chaqnaydi". Modul skriptlar esa kechiktirib bajariladi. Shuning uchun tema.js oddiy skript bo'lib qolishi kerak. Vite faqat modullarni grafga oladi va oddiy skriptni "tegmayman" deb ogohlantiradi.
Yechim vite.config.ts da: tema.ts ni ikkinchi entry qilamiz va chiqish nomini o'zgarmas (assets/js/tema.js) qilamiz, toki index.html dagi manzil ishlayversin. Ogohlantirish qoladi — u "bu skriptni o'zing nazorat qil" degan ma'lumot.
6.2 Raqamlar
Asboblar zanjiri darsining 3-mashqida yozgan olcha.mjs bilan dist/ ni o'lchaymiz (kurs/mashqlar/16/01-hajm/ papkasidan):
node olcha.mjs ../../../vazifalar/distassets/index-BI1hyTgJ.css 3596 1290
assets/index-BewOu_Dy.js 25864 9595
assets/js/tema.js 128 127
assets/olchov-G4bloHwN.js 8878 3364
JAMI: 4 fayl, 38.5 KB, gzip 14.4 KB- holat 16: tsc + nusxalash21 fayl, 20 so'rov32 KB
- holat 20: vite build4 fayl14,4 KB
Manba: O'lchandi: vazifalar holat 16 va 20 dist/, olcha.mjs (gzip -9), Node 24.21.0, Vite 8.3.3, 2026-10-10
Xom hajm 85.8 → 38.5 KB, gzip 32.0 → 14.4 KB, brauzer yuklaydigan fayllar 20 → 4 (diskdagi 21 ta JS va CSS dan turlar.js so'ralmaydi — u bo'sh modul). Bularning hammasi — bitta buyruq. 16-qism oxirida (source map, target va boshqa qadamlardan keyin) — 38.1 va 14.3 KB.
7. Ko'p uchraydigan xatolar
7.1 public/ siz: manifest buzildi
vazifalar ga Vite qo'shishning birinchi urinishida sw.js, manifest va ikonlar eski joyida qoldi. Vite ularni ham "asset" deb ko'rdi (manifest index.html dagi <link> da):
dist/assets/ikon-CdIzd46i.svg 0.27 kB │ gzip: 0.20 kB
dist/assets/manifest-faQiLkSt.webmanifest 0.67 kB
dist/assets/ikon-180-ew4y6vgh.png 1.10 kBVa index.html da: <link rel="manifest" href="./assets/manifest-faQiLkSt.webmanifest">. Uch muammo: manifest ichidagi ikon yo'llari endi noto'g'ri papkaga qaraydi; sw.js umuman dist/ ga tushmadi (uni hech kim import qilmaydi — grafda yo'q); Service Worker nomi o'zgarmasligi shart edi.
Yechim — public/ papkasi. Undagi fayllar grafga kirmaydi: Vite ularni dist/ ga o'zgarishsiz, o'sha nom bilan ko'chiradi. Nomi doim bir xil bo'lishi kerak bo'lgan fayllar (sw.js, manifest.webmanifest, robots.txt, favicon) — public/ ga. Batafsil — Vite IV darsida.
7.2 Yashil test aldaydi: blocking="render"
Vite <script type="module"> ni hash'li nom bilan qayta yozadi — va bizning blocking="render" atributimiz (DevTools: Performance darsidan) tushib qoldi. Natija: ro'yxat birinchi kadrda chizilmay, sahifa siljidi — brauzer tekshiruvi [Web Vitals] CLS: 0.057 ko'rsatdi (avval 0). Eng xavflisi: CLS tekshiruvi index.html da atribut bo'lmasa, o'tkazib yuborilardi va natija "HAMMASI " edi.
Tuzatish — vite.config.ts dagi 10 qatorli plagin: u Vite yozgan HTML'ga atributni qaytaradi. Saboq: bundler kodingizni qayta yozadi — build natijasini (dist/) tekshiring, manbani emas.
7.3 dist/ ni file:// bilan ochish
Vite yo'llari modul skriptlar — file:// da CORS xatosi (Asboblar zanjiri darsida ko'rganmiz). Build natijasini server orqali oching; Vite I da npm run preview qo'shamiz.
8. Mashqlar
Mashqlar kurs/mashqlar/16/20-bundler/ da.
1-mashq (oson): Atamani toping
«Bahor» menyusi build'i bo'yicha:
- Graf boshlanadigan JS fayl:
- Tugma bosilganda yuklanadigan chunk qaysi modul uchun:
- Grafdagi modullar soni (
modules transformed): - JS bo'lmagan, nomiga hash qo'shilgan ikki fayl turi: CSS va
Yechim
Entry — main.js (index.html uni <script type="module"> bilan ulaydi). Dinamik chunk — report.js. Grafda 10 ta modul: 6 ta o'zimizniki, index.html va Vite qo'shgan yordamchilar. Assetlar — index-….css va logo-….svg. Agar --assetsInlineLimit 0 siz yig'sangiz, SVG asset bo'lib chiqmaydi — u 4 KB dan kichik, JS ichiga joylanadi.
2-mashq (o'rta): Kichik loyihani yig'ing
Darsdagi menyu/ loyihasini yarating (npm init -y, npm pkg set type=module, npm i -D -E vite@8.3.3). So'ng:
npx vite build(bayroqsiz).dist/assets/da nechta fayl? SVG qayerda?report.jsgaimport { dishes } from "./dishes.js";qo'shing va qayta yig'ing. Chunk'lar soni o'zgardimi?main.jsdagiawait import("./report.js")ni oddiyimport { buildReport } from "./report.js";ga almashtiring. Endi nechta JS chunk?
Yechim
- Uchta:
index-….js,report-….js,index-….css. SVG —index-….jsichidadata:image/svg+xml,…bo'lib turibdi (assetsInlineLimitsukut — 4 KB). - O'zgarmadi — ikkita.
dishes.jsentry chunk'ida qoladi,reportchunk'i uni o'sha yerdan import qiladi. - Bitta. Statik import — "sahifa ochilishida kerak" degani, shuning uchun
report.jsham entry chunk'iga qo'shildi. Dinamikimport()— bundlerga "buni alohida qil" degan yagona signal.
3-mashq (qiyin): Grafni ko'rsatadigan plagin
vite.config.js yozing: unda generateBundle hook'iga ulangan plagin har chiqish faylini chiqarsin — chunk bo'lsa, entry yoki dinamik ekanini va ichidagi modullar ro'yxatini.
Ishoralar:
generateBundle(options, bundle)—bundleobyektida har chiqish fayli:type("chunk"yoki"asset"),fileName, chunk'daisEntryvamodules(kalitlari — modul yo'llari).- Yo'llar to'liq (
C:/…/src/main.js) keladi —node:pathdagirelative(process.cwd(), id)bilan qisqartiring. - Vite o'zi yasagan modul yo'li
"\0"(nol belgi) bilan boshlanadi — uni olib tashlang.
Yechim
// vite.config.js — build'dan keyin har chunk ichidagi modullar
import { relative } from "node:path";
import { defineConfig } from "vite";
export default defineConfig({
build: { assetsInlineLimit: 0 },
plugins: [
{
name: "graf-korsat",
generateBundle(_options, bundle) {
for (const file of Object.values(bundle)) {
if (file.type === "asset") {
console.log(`asset ${file.fileName}`);
continue;
}
const kind = file.isEntry ? "entry" : "dinamik";
console.log(`chunk ${file.fileName} (${kind})`);
for (const id of Object.keys(file.modules)) {
// "\0" bilan boshlangan — Vite o'zi yasagan modul
const name = id.startsWith("\0")
? id.slice(1)
: relative(process.cwd(), id).replaceAll("\\", "/");
console.log(` ← ${name}`);
}
}
},
},
],
});npx vite build chiqishi — «Chunk» bo'limidagi ro'yxat. Plaginning tuzilishi — name va hook funksiyalari bo'lgan oddiy obyekt. _options oldidagi pastki chiziq — "bu parametr ishlatilmaydi" degan kelishuv. Bunday plaginlarni Vite plaginlari darsida yozishni davom ettiramiz.
4-mashq: Vazifalar qadami — vite build
vazifalar da tsc faqat tekshiradi, JavaScript'ni Vite yozadi.
- Branch:
build/vite - Commit:
build: vite build — tsc emit va nusxala.js o'rniga; public/, qobiq.js(tana bilan)
npm i -D vite@8.3.3;web-vitalsnidependenciesga o'tkazing (endi u brauzer kodiga kiradi — bog'liqlik turlari):npm i web-vitals@6.2.3.olchov.ts:from "./vendor/web-vitals.js"→from "web-vitals".assets/js/vendor/,skriptlar/vendor.jsvanpm run vendorni o'chiring.index.html: 15 tamodulepreloadni o'chiring (Vite kerak bo'lsa o'zi qo'yadi),src="assets/js/asosiy.js"→asosiy.ts.sw.js,manifest.webmanifest,assets/ikonlar/→public/ga (yo'llaridist/da o'sha-o'sha qoladi).skriptlar/nusxala.jsni o'chiring.tsconfig.json:noEmit: true,allowImportingTsExtensions: true(rewriteRelativeImportExtensions,outDir,rootDiro'rniga).vite.config.tsvaskriptlar/qobiq.js(Service Worker qobig'ini build'dan keyin yozadi).package.json:"build": "tsc && vite build","postbuild": "node skriptlar/qobiq.js",prebuildo'chadi (Vitedist/ni o'zi tozalaydi).
Yechim
vite.config.ts:
// vite.config.ts — build sozlamasi (16/#20). Vite index.html dan
// boshlab import grafini quradi: asosiy.ts → render.ts → ... va
// hammasini bir nechta faylga (chunk) yig'adi
import { defineConfig } from "vite";
export default defineConfig({
plugins: [
{
// Vite <script type="module"> ni o'zi qayta yozadi (hash'li nom
// bilan) va blocking="render" tushib qoladi. U kerak
// (13/#30): ro'yxat birinchi kadrda chiziladi, CLS 0.
// Plaginlar — 16/#31
name: "blocking-render",
transformIndexHtml: {
order: "post",
handler: (html) =>
html.replace(
'<script type="module" crossorigin',
'<script type="module" blocking="render" crossorigin',
),
},
},
],
// Sayt login.github.io/vazifalar/ da: yo'llar nisbiy
// ("./assets/...") — papka nomi qanday bo'lsa ham ishlaydi
base: "./",
build: {
rolldownOptions: {
input: {
index: "index.html",
// tema.ts — <head> dagi ODDIY skript (modul emas): sahifa
// chizilishidan oldin ishlaydi. Vite type="module" siz
// <script> ni yig'maydi — alohida kirish nuqtasi qilamiz
tema: "assets/js/tema.ts",
},
output: {
// tema.js nomi o'zgarmaydi: index.html shu nom bilan so'raydi
entryFileNames: (chunk) =>
chunk.name === "tema"
? "assets/js/tema.js"
: "assets/[name]-[hash].js",
},
},
},
});Kalitlar qatorma-qator:
| Kalit | Nima qiladi | Sukut |
|---|---|---|
plugins |
build bosqichlariga ulanadigan plaginlar | [] |
base |
dist/ dagi yo'llar prefiksi |
"/" |
rolldownOptions.input |
entry'lar (nom → fayl) | index.html |
output.entryFileNames |
entry chunk'lar nomi | assets/[name]-[hash].js |
base: "./" — GitHub Pages sayti login.github.io/vazifalar/ da turadi. "/" bo'lsa, brauzer /assets/… ni domen ildizidan izlardi va 404 olardi. [name]-[hash] — chunk nomi va tarkib hash'i (hash bilan keshlash darsida).
skriptlar/qobiq.js (asosiy qismi) — dist/ dagi hamma faylni sw.js ning QOBIQ ro'yxatiga, tarkib hash'ini VERSIYA ga yozadi. Hash'li nomlarni endi qo'lda yozib bo'lmaydi — ro'yxatni build'ning o'zi tuzadi:
const royxat = qobiqRoyxati(fayllar);
// Tarkib o'zgarsa — VERSIYA ham (yangi kesh)
const hash = createHash("sha256");
for (const yol of royxat.slice(1)) {
hash.update(yol).update(readFileSync(new URL(yol, dist)));
}
const versiya = `v6-${hash.digest("hex").slice(0, 8)}`;Natija — «vazifalar ning grafi» bo'limidagi chiqish: 4 ta yuklanadigan fayl, dist/ da jami 29 o'rniga 12 fayl, sw.js: QOBIQ — 12 ta. dist/index.html da:
<script src="assets/js/tema.js"></script>
<script type="module" blocking="render" crossorigin
src="./assets/index-BewOu_Dy.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-BI1hyTgJ.css">CSP (script-src 'self') bir harf ham o'zgarmagan: inline skript yo'q, hamma fayl o'z domenimizdan.
Testlar: 143 → 145 (qobiq.test.js +3; sw.test.js dagi diskdagi modullarni QOBIQ bilan solishtiruvchi 2 test endi ma'nosiz — nomlarda hash — o'rniga bitta "manbada faqat sahifa" testi). Brauzer: 159/159, SW oflayn ham.
Commit va PR — sarlavha 71 belgi (≤ 72), tafsilot commit tanasida (ikkinchi -m). Qo'shtirnoq ichidagi \ va yangi qator — telefon ekraniga sig'ishi uchun: shell ularni olib tashlab, satrni birlashtiradi.
git switch -c build/vite
npm run build && npm test && npm run lint
npm run format:check
git add -A
git commit -m \
"build: vite build — tsc emit va nusxala.js o'rniga;\
public/, qobiq.js" \
-m "web-vitals npm'dan (vendor/ o'chdi);\
blocking=render plagini; e2e bor()"
git push -u origin build/vite
gh pr create --fill
gh pr merge --mergeDiff: 25 fayl, +965 −192 (lock bilan).
9. Real ishda
- Har zamonaviy frontend loyihasi bundler bilan quriladi: Vite (React, Vue, Svelte shablonlari), Next.js ichida Turbopack, eski loyihalarda webpack. Atamalar — entry, chunk, asset — hammasida bir xil.
- "Nega sahifa sekin?" savoliga javob ko'pincha grafda: katta kutubxona entry chunk'iga tushib qolgan. Buni ko'rish uchun bundle tahlili kerak — Vite V darsida.
- Intervyu savollari: "Bundler nima qiladi?", "Chunk va asset farqi?", "Dinamik import bundle'ga qanday ta'sir qiladi?", "Dev va production build farqi?".
Xulosa
- Bundler entry'dan boshlab
importlarni kuzatib bog'liqlik grafini quradi; grafdagi har fayl — modul. - Statik importlar entry chunk'iga, dinamik
import()— alohida chunk'ga; umumiy modul bir marta, chunk'lar bir-biridan import qiladi. - Asset — CSS, rasm, shrift: hash'li nom bilan chiqadi, 4 KB dan kichigi JS ichiga joylanadi;
public/dagi fayllar grafga kirmaydi va o'zgarishsiz ko'chadi. - Plagin hook'lar orqali build'ga ulanadi; Vite'da loader yo'q — hammasi plagin.
vazifalar:vite buildbilan brauzer yuklaydigan fayllar 20 → 4, gzip 32.0 → 14.4 KB;tema.js— ikkinchi entry,blocking="render"— o'z plaginimiz.
Keyingi dars: Transpilyatsiya: Babel, SWC, esbuild va Oxc — bundler grafni quradi, lekin .ts va yangi sintaksisni kim o'giradi? Transpilerlar ichiga — AST darajasida — qaraymiz.
Manbalar
- Vite: "Building for Production", "Static Asset Handling" (
assetsInlineLimit,public/), "Build Options" — vite.dev/guide, vite.dev/config/build-options - Rolldown: "Plugin API" (
generateBundle,OutputChunk) — rolldown.rs - Rollup: "Plugin Development → Build Hooks / Output Generation Hooks" — rollupjs.org
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!