Mundarija (25)
- Bu darsda
- 1. Nega bu kerak?
- 2. Bo'laklarga bo'lish
- 2.1 Dinamik import — eslatma
- 2.2 Vendor chunk
- 2.3 Qachon bo'lmaslik kerak
- 3. Content hash
- 3.1 Hash qachon o'zgaradi
- 3.2 Hash zanjiri
- 4. Kesh sarlavhalari
- 4.1 Ikki xil fayl — ikki xil qoida
- 4.2 GitHub Pages'da
- 5. modulepreload
- 6. "Eski chunk topilmadi"
- 6.1 Xatoni yaratamiz
- 6.2 Uch yechim
- 7. Ko'p uchraydigan xatolar
- 8. Mashqlar
- 1-mashq (oson): Kesh qoidasi
- 2-mashq (o'rta): Hash zanjirini kuzating
- 3-mashq (qiyin): Ikki build'ni solishtirish
- 4-mashq: Amaliy tajriba — vazifalar da o'lchov
- 9. Real ishda
- Xulosa
- Manbalar
Code splitting va hash bilan keshlash: dinamik import, vendor chunk va eski chunk xatosi
Qisqacha: Code splitting — bundle'ni bir nechta chunk'ga bo'lish: dinamik
import()kod faqat kerak bo'lganda yuklanadigan chunk yaratadi, vendor chunk esa kam o'zgaradigan kutubxonalarni alohida faylga ajratadi. Fayl nomidagi content hash (index-ys8EmKCO.js) tarkib o'zgarsa o'zgaradi — shuning uchun hash'li faylni brauzer bir yil keshlasa bo'ladi (Cache-Control: immutable),index.htmlesa har safar tekshiriladi. Bitta tuzoq: sahifa ochiq turganda yangi versiya chiqsa, eski chunk serverdan yo'qoladi vaFailed to fetch dynamically imported modulexatosi chiqadi.
Bu darsda
- Dinamik import va vendor chunk qanday chunk yaratishini va qachon bo'lish foyda emas, zarar ekanini bilasiz.
- Content hash qachon o'zgarishini haqiqiy build'larda kuzatasiz — "hash zanjiri" bilan.
Cache-Control: immutable,no-cacheva hash birgalikda qanday ishlashini tushuntira olasiz.modulepreloadnima uchun qo'shilishini bilasiz.- "Eski chunk topilmadi" xatosini Chrome'da qayta yaratasiz va
vite:preloadErrorbilan yechasiz.
Oldin bilishingiz kerak: Dinamik import va top-level await, HTTP sarlavhalari, MIME turlari va kesh, Bundler nima, Source map'lar.
1. Nega bu kerak?
Dinamik import darsida g'oyani ko'rdik: kod kerak bo'lgandagina yuklansin. Bundler nima darsida bundler import() ni ko'rib, alohida chunk yasaganini ko'rdik. Bugun ikki savolni chuqurroq beramiz.
Birinchisi — qachon bo'lish kerak. Har chunk — alohida so'rov. Kichik loyihada ko'p chunk sahifani tezlashtirish o'rniga sekinlashtirishi mumkin.
Ikkinchisi — kesh. Sardor «Bahor» saytining narxini o'zgartirdi va deploy qildi. Jasur aka telefonidan ochdi — eski narx. "Keshni tozalang" — bu foydalanuvchidan so'raladigan narsa emas. Fayl nomidagi hash aynan shu muammoni yechadi. Lekin hash o'zining yangi muammosini olib keladi — darsning oxirida.
Hayotiy o'xshatish: «Bahor» menyusi kitobchasi. Har oy chop etilgan yangi nashrning muqovasida sana bor ("2026-oktabr"). Ofitsiant stolga qarab biladi: sana o'zgarmagan bo'lsa — eski kitobcha yaroqli, o'zgargan bo'lsa — almashtirish kerak. Hash — fayl muqovasidagi shu "sana", faqat u tarkibdan hisoblanadi.
Maslahat: Chiqishlar 2026-10-10 da Vite 8.3.3 (Rolldown 1.2.12), Node 24.21.0 va Chrome 154.0.8037.98 (headless) bilan. Misol — Bundler nima darsidagi «Bahor» menyusi loyihasi.
2. Bo'laklarga bo'lish
2.1 Dinamik import — eslatma
Menyu loyihasida hisobot tugma bosilganda yuklanadi:
const button = document.querySelector("#hisobot");
button.addEventListener("click", async () => {
const { buildReport } = await import("./report.js");
console.log(buildReport(dishes));
});Build'da — alohida report-….js chunk (0.15 kB). Bu route-level ("sahifa darajasidagi") bo'lishning kichik nusxasi: katta ilovalarda har sahifa (/menyu, /buyurtmalar, /admin) o'z chunk'i bo'ladi va foydalanuvchi faqat ochgan sahifasining kodini yuklaydi. React'da buni lazy bilan qilamiz — 17–18-qismlarda.
2.2 Vendor chunk
Menyuga buyurtma raqami uchun nanoid (6.0.2) qo'shdik. Sukut bo'yicha u ilova kodi bilan bitta index chunk'iga tushadi. Vendor chunk — node_modules dagi kutubxonalarni alohida faylga ajratish. Vite 8 da bu Rolldown'ning codeSplitting sozlamasi bilan:
// vite.config.js — node_modules dan kelgan kod — alohida chunk
import { defineConfig } from "vite";
export default defineConfig({
build: {
assetsInlineLimit: 0,
rolldownOptions: {
output: {
codeSplitting: {
groups: [{ name: "vendor", test: /node_modules/ }],
},
},
},
},
});dist/assets/logo-mWEg-Urw.svg 0.11 kB │ gzip: 0.12 kB
dist/index.html 0.45 kB │ gzip: 0.28 kB
dist/assets/index-CRKnUwHd.css 0.06 kB │ gzip: 0.08 kB
dist/assets/report-BShP2LZ6.js 0.15 kB │ gzip: 0.15 kB
dist/assets/vendor-DkLq5wXv.js 0.18 kB │ gzip: 0.19 kB
dist/assets/index-CKYfbSeg.js 2.70 kB │ gzip: 1.33 kBChiqishda yangi qatorga qarang: vendor-….js paydo bo'ldi, index esa nanoid'siz qoldi.
| Kalit | Nima qiladi | Sukut |
|---|---|---|
output.codeSplitting |
chunk'larga bo'lish qoidalari | yoqiq: har dinamik import() — alohida chunk |
groups |
modullarni nomli chunk'larga yig'ish | yo'q — guruh yo'q |
groups[].name |
chunk nomi (fayl nomining boshi) | majburiy |
groups[].test |
qaysi modul yo'llari shu guruhga | — |
groups — "qaysi modullar qaysi chunk'ga": test regex'iga mos keladigan yo'llar (node_modules ichidagilar) vendor ga. Vite'ning oldingi versiyalarida va webpack'da shu ishni manualChunks qilardi. Rolldown'ning oraliq nomi advancedChunks ham bor, lekin Vite 8.3.3 uni ogohlantirish bilan qabul qiladi:
WARN advancedChunks option is deprecated, please use codeSplitting instead."advancedChunks eskirgan, o'rniga codeSplitting ishlating". Internetdagi maqolalarda uchta nomni ham ko'rasiz — sizning Vite versiyangiz hujjatiga qarang.
Nega vendor ajratiladi — keyingi bo'limda, hash bilan birga ko'rinadi.
2.3 Qachon bo'lmaslik kerak
vazifalar da o'lchov qildik. Eng kam ishlatiladigan modul — fayl.ts (vazifalarni faylga eksport qilish): minifikatsiyadan oldin 629 bayt. Uni dinamik import qilsak — 629 baytni tejash uchun yangi HTTP so'rov qo'shiladi, va tugma bosilganda foydalanuvchi uni kutadi. So'rovning o'zi (sarlavhalar, kutish) bundan qimmat. Shuning uchun vazifalar da faqat bitta qo'shimcha chunk bor: olchov — web-vitals bilan 8.87 kB, sahifaning birinchi chizilishiga kerak emas.
Taxminiy qoida: chunk o'nlab kilobayt bo'lsa va sahifa ochilishida kerak bo'lmasa — ajrating. Bir necha yuz bayt — ajratmang.
Tekshirib ko'ring: Sardor har funksiyani alohida
import()qildi: "faqat kerakligi yuklansin". Sahifa ochilishi sekinlashdi. Nega?
Javob
Har import() — alohida so'rov va kutish. Ko'pchilik funksiya baribir birinchi ekranda kerak: brauzer avval asosiy faylni oladi, keyin uning ichidagi import() larni ko'rib, birma-bir so'raydi — "sharshara". Bundan tashqari, gzip kichik fayllarni yomonroq siqadi. Bo'lish — faqat katta va kechiktirsa bo'ladigan qismlar uchun.
3. Content hash
3.1 Hash qachon o'zgaradi
Content hash — fayl tarkibidan hisoblangan qisqa satr: index-ys8EmKCO.js dagi ys8EmKCO. Tarkib bir bayt o'zgarsa, hash butunlay boshqa bo'ladi; o'zgarmasa — aynan o'sha.
Tajriba (vendor'siz loyihada): dishes.js da ko'k choy narxini 5 000 dan 6 000 ga o'zgartirib, qayta build qildik. Ikki build chiqishining farqi (diff):
< dist/assets/report-12McAH2s.js 0.15 kB │ gzip: 0.15 kB
< dist/assets/index-ys8EmKCO.js 2.64 kB │ gzip: 1.30 kB
---
> dist/assets/report-DIyMfzhE.js 0.15 kB │ gzip: 0.15 kB
> dist/assets/index-n11KLlOe.js 2.64 kB │ gzip: 1.30 kBindex o'zgardi — tushunarli, dishes.js unda. logo.svg va CSS — o'zgarmadi. Lekin report ham o'zgardi! Uning kodiga tegmadik-ku.
3.2 Hash zanjiri
Sababi — chunk'lar bir-birini nomi bilan import qiladi. report chunk'ining birinchi satrini Bundler nima darsida ko'rgan edik:
import{t as e}from"./index-ys8EmKCO.js";…index ning nomi o'zgardi → report ichidagi import satri o'zgardi → report ning tarkibi o'zgardi → uning hash'i ham. Teskarisi ham to'g'ri: faqat report.js ni o'zgartirsak, index ham o'zgaradi — unda import("./report-….js") yozilgan.
flowchart LR
D["dishes.js<br/>o'zgardi"] --> I["index-….js<br/>yangi hash"]
I --> R["report-….js<br/>ichida index nomi<br/>→ yangi hash"]
V["vendor-….js"] -. "index'ni import<br/>qilmaydi" .-> X["o'zgarmaydi"]Vendor chunk'ning foydasi shu yerda. Vendor bilan bir xil tajriba — 3-mashqdagi skript bilan solishtirildi:
keshda qoladi: index-CRKnUwHd.css, logo-mWEg-Urw.svg, vendor-DkLq5wXv.js
qayta yuklanadi: index-CKYfbSeg.js → index-Bs_S3381.js, report-BShP2LZ6.js → report-CLFRUp4l.jsvendor o'zgarmadi: u ilova kodini import qilmaydi, shuning uchun zanjir unga yetib bormaydi. Haqiqiy loyihada vendor chunk yuzlab kilobayt (React, router, sana kutubxonasi) bo'ladi — kodingizdagi har kichik o'zgarishda u qayta yuklanmaydi. Bizning nanoid misolida esa bu foyda deyarli sezilmaydi (0.18 kB) — vendor chunk katta kutubxonalar uchun.
Tekshirib ko'ring: Nega hash'ni sana yoki versiya raqamidan emas (
index-v6.js), aynan tarkibdan hisoblash kerak?
Javob
Versiya raqami hamma fayl uchun bir vaqtda o'zgaradi — bitta qator tuzatilsa ham, foydalanuvchi hamma faylni qayta yuklaydi. Tarkib hash'i esa faqat haqiqatan o'zgargan fayllarni yangilaydi: CSS, rasm, vendor — keshda qoladi. Bundan tashqari, bir xil tarkib har kompyuterda bir xil nom beradi — build qayta takrorlanadigan (deterministik) bo'ladi.
4. Kesh sarlavhalari
4.1 Ikki xil fayl — ikki xil qoida
HTTP sarlavhalari va kesh darsidan Cache-Control ni bilasiz. Hash'li build'da fayllar ikki turga bo'linadi:
| Fayl | Nomi o'zgaradimi | Cache-Control |
|---|---|---|
assets/index-ys8EmKCO.js, CSS, rasm |
ha, tarkib bilan | public, max-age=31536000, immutable |
index.html |
yo'q — doim index.html |
no-cache |
max-age=31536000, immutable— "bir yil saqla va hech qachon qayta tekshirma". Xavfsiz: tarkib o'zgarsa — nom o'zgaradi, eski nom bilan eski tarkib abadiy to'g'ri.no-cache— "saqlasang ham, har safar serverdan so'ra: o'zgarganmi?".index.html— yangi hash'li fayllarga yo'l ko'rsatadigan yagona fayl. U eskirsa — foydalanuvchi eski JS'ni oladi.
sequenceDiagram
participant B as Brauzer
participant S as Server
B->>S: index.html (no-cache)
S-->>B: yangi index.html → index-Bs_S3381.js
B->>S: index-Bs_S3381.js
S-->>B: 200 (bir yilga keshlanadi)
Note over B: vendor-DkLq5wXv.js — keshda,<br/>so'rov ham yo'q4.2 GitHub Pages'da
Asboblar zanjiri darsida curl -I bilan ko'rgan edik: GitHub Pages hamma faylga Cache-Control: max-age=600 beradi va uni o'zgartirib bo'lmaydi. Ya'ni vazifalar da hash'li fayllar 10 daqiqadan keyin qayta tekshiriladi (ular baribir o'zgarmagan — server "o'zgarmagan" deb qisqa javob beradi), index.html esa 10 daqiqagacha eski bo'lishi mumkin. Sarlavhalarni o'zingiz boshqaradigan server (nginx) — 33-qismda.
5. modulepreload
index.html da vendor bilan build'dan keyin yangi qator paydo bo'ldi:
<script type="module" crossorigin
src="/assets/index-CKYfbSeg.js"></script>
<link rel="modulepreload" crossorigin
href="/assets/vendor-DkLq5wXv.js">Brauzerda ESM darsidan: brauzer index ni yuklab, ichidagi import ni ko'rgandagina vendor ni so'raydi — ikki bosqich. modulepreload brauzerga oldindan aytadi: "bu ham kerak bo'ladi, hozirdan yuklay ber". Vite uni statik bog'liq chunk'lar uchun o'zi qo'shadi. Dinamik chunk'lar uchun esa vite/preload-helper.js ishlaydi: import("./report.js") dan oldin report ning bog'liqliklarini parallel yuklaydi.
vazifalar da modulePreload: false ni ham sinadik — chiqish bayt-bayt bir xil. Bizning yagona dinamik chunk (olchov) boshqa chunk'larga bog'liq emas, oldindan yuklaydigan narsa yo'q. Shuning uchun kanonda faqat polyfill o'chirilgan (Polyfill va Baseline).
6. "Eski chunk topilmadi"
6.1 Xatoni yaratamiz
Mana hash'ning narxi. Ssenariy:
- Foydalanuvchi sahifani ochdi — brauzerda
index-CKYfbSeg.js(ureport-BShP2LZ6.jsni import qiladi). - Shu payt yangi versiya deploy qilindi.
report.jso'zgardi,dist/yangidan yozildi —report-BShP2LZ6.jsserverda yo'q. - Foydalanuvchi «Kunlik hisobot» tugmasini bosdi.
Buni puppeteer (Chrome 154) va kichik lokal server bilan aynan shunday qildik — server har so'rovni chiqaradi:
200 /
200 /assets/index-CKYfbSeg.js
200 /assets/vendor-DkLq5wXv.js
200 /assets/index-CRKnUwHd.css
--- yangi deploy (vite build)
--- tugma bosildi
404 /assets/report-BShP2LZ6.js
konsol: Failed to load resource: the server responded with a status of 404 (Not Found)
xato: Failed to fetch dynamically imported module: http://localhost:5741/assets/report-BShP2LZ6.jsChrome konsolida: Uncaught (in promise) TypeError: Failed to fetch dynamically imported module: …/report-BShP2LZ6.js — "dinamik import qilingan modulni yuklab bo'lmadi". Tugma ishlamaydi, foydalanuvchi sababini bilmaydi. Firefox'da matn boshqa (error loading dynamically imported module), ma'nosi bir xil.
6.2 Uch yechim
1. Xatoni ushlash. vazifalar da olchov importi 15-qismdan beri .catch bilan yozilgan:
import("./olchov.ts")
.then(({ olchashniBoshla }) => olchashniBoshla())
.catch((xato: unknown) => {
console.warn(`Web Vitals yuklanmadi: ${xatoMatni(xato)}`);
});O'lchov yuklanmasa — ilova ishlayveradi, faqat ogohlantirish. Ixtiyoriy funksiya uchun bu yetarli.
2. Sahifani yangilash. Vite dinamik import yiqilganda window da vite:preloadError hodisasini chiqaradi. Uni tinglab, sahifani qayta yuklash mumkin — yangi index.html yangi chunk nomlarini beradi:
// Deploydan keyin eski chunk topilmasa — sahifani yangilaymiz
window.addEventListener("vite:preloadError", () => {
console.log("eski chunk topilmadi — sahifa yangilanadi");
location.reload();
});Shu kod bilan bir xil ssenariy:
404 /assets/report-BXufKShm.js
konsol: eski chunk topilmadi — sahifa yangilanadi
xato: Failed to fetch dynamically imported module: http://localhost:5741/assets/report-BXufKShm.js
200 /
200 /assets/index-_vhnfq19.jsSahifa o'zi yangilandi va yangi index ni oldi. Foydalanuvchi tugmani yana bir bosadi — ishlaydi. Ehtiyot bo'ling: forma yarim to'ldirilgan bo'lsa, yangilash uni o'chiradi.
3. Eski fayllarni o'chirmaslik. Eng ishonchli yo'l — deploy'da eski assets/ fayllarni bir necha kun serverda qoldirish. Hash'li nomlar to'qnashmaydi, shuning uchun eski va yangi versiya yonma-yon yashay oladi. Ko'p hosting xizmatlari (Vercel, Netlify) buni o'zi qiladi; GitHub Pages esa har deploy'da dist/ ni to'liq almashtiradi.
vazifalar da yana bir himoya bor: Service Worker. U qobiqdagi hamma faylni (Bundler nima darsidagi qobiq.js) keshda saqlaydi — yangi SW faollashguncha eski versiya o'z chunk'lari bilan to'liq ishlaydi.
Tekshirib ko'ring: Nega bu xato faqat dinamik import'da chiqadi, statik importlarda deyarli yo'q?
Javob
Statik importlar sahifa ochilganda, bir vaqtda yuklanadi — bir necha soniyalik oraliqda deploy tushib qolishi juda kam. Dinamik import esa soatlab keyin — foydalanuvchi tugmani bosganda — yuklanadi. Shu vaqt ichida yangi versiya chiqib, eski fayl o'chib ketishi mumkin.
7. Ko'p uchraydigan xatolar
| Xato | Oqibati | To'g'risi |
|---|---|---|
index.html ga ham uzoq kesh |
foydalanuvchi eski versiyada qoladi | index.html — no-cache |
hash'siz nomga immutable |
yangilanish hech qachon yetmaydi | immutable faqat hash'li fayllarga |
har kichik modulni import() |
ko'p so'rov, "sharshara" | o'nlab KB lik chunk'lar |
dinamik import .catch siz |
deploydan keyin tugma "o'ladi" | .catch yoki vite:preloadError |
manualChunks ni Vite 8 da ko'chirish |
eskirgan nom, ogohlantirish | codeSplitting.groups |
8. Mashqlar
Mashqlar kurs/mashqlar/16/25-code-splitting/ da.
1-mashq (oson): Kesh qoidasi
Har fayl uchun Cache-Control tanlang (immutable yoki no-cache):
index.html:assets/index-ys8EmKCO.js:assets/logo-mWEg-Urw.svg:sw.js(nomi doim bir xil):
Yechim
Hash'li fayllar — immutable: tarkib o'zgarsa, nom o'zgaradi. Nomi doimiy fayllar (index.html, sw.js, manifest.webmanifest) — no-cache: ular yangi versiyaga "eshik". sw.js ni brauzer o'zi ham ko'pi bilan 24 soatda qayta tekshiradi, lekin server sarlavhasi baribir no-cache bo'lgani yaxshi.
2-mashq (o'rta): Hash zanjirini kuzating
Bundler nima darsidagi menyu loyihasida (vendor'siz):
- Build qiling, chiqishni saqlang (
npx vite build > b1.txt). - Faqat
report.jsdagi matnni o'zgartiring (Jami→Jami:), qayta build,diff. - Faqat
menyu.cssdagi rangni o'zgartiring. Qaysi fayllar o'zgardi?
Yechim
reportvaindexo'zgaradi:indexichidaimport("./report-….js")— nom bilan.Biz sinaganda kutilmagan natija chiqdi: CSS,
index.html— va ikkala JS chunk ham o'zgardi (index-DPzHSyF5.js→index-DaoVmbxj.js). Faqat SVG o'sha qoldi. Sabab: Vite CSS'ni entry chunk'ining moduli deb hisoblaydi (Bundler nima darsidagi grafdasrc/menyu.cssindexchunk ichida edi) va chunk hash'iga CSS fayl nomi ham kiradi. Saboq: hash zanjirini taxmin qilmang — o'lchang. 3-mashqdagi skript aynan shuning uchun kerak.
3-mashq (qiyin): Ikki build'ni solishtirish
hash-solishtir.mjs yozing: ikki dist/assets papkasini oladi va chiqaradi — qaysi fayl keshda qoladi (nomi bir xil), qaysi biri qayta yuklanadi (hash o'zgargan), qaysi biri yangi, qaysi biri o'chgan.
Ishoralar: hash — 8 belgi, harf, raqam, _ yoki -, nuqta va kengaytmadan oldin: /-[\w-]{8}(?=\.\w+$)/ (lookahead). Uni olib tashlasangiz, "kalit" qoladi: index-ys8EmKCO.js → index.js. Eski fayllarni Map ga (kalit → nom) joylang (Map).
Yechim
// hash-solishtir.mjs — ikki build: nima keshda qoladi (nom o'sha),
// nima qayta yuklanadi (hash o'zgargan)
import { readdirSync } from "node:fs";
// "index-ys8EmKCO.js" → "index.js" (hash'siz "kalit")
export function baseName(file) {
return file.replace(/-[\w-]{8}(?=\.\w+$)/, "");
}
export function compareBuilds(before, after) {
const old = new Map(before.map((f) => [baseName(f), f]));
const result = { kept: [], changed: [], added: [], removed: [] };
for (const file of after) {
const prev = old.get(baseName(file));
if (prev === file) result.kept.push(file);
else if (prev) result.changed.push(`${prev} → ${file}`);
else result.added.push(file);
old.delete(baseName(file));
}
result.removed = [...old.values()];
return result;
}
// node hash-solishtir.mjs eski-dist/assets yangi-dist/assets
if (import.meta.main) {
const [a, b] = process.argv.slice(2).map((d) => readdirSync(d));
const r = compareBuilds(a.sort(), b.sort());
console.log("keshda qoladi:", r.kept.join(", ") || "—");
console.log("qayta yuklanadi:", r.changed.join(", ") || "—");
if (r.added.length) console.log("yangi:", r.added.join(", "));
if (r.removed.length) console.log("o'chdi:", r.removed.join(", "));
}Ikki test bilan (ℹ tests 2, ℹ pass 2). Vendor'li loyihada narx o'zgargandan keyin — «Hash zanjiri» bo'limidagi chiqish: CSS, SVG, vendor — keshda; index va report — qayta yuklanadi.
Kamchiligi: logo-mWEg-Urw.svg dagi hash ichida - bor — regex buni hisobga oladi ([\w-]). Lekin nomning o'zida - va 8 belgi bo'lsa (menu-sections.js), hash'siz fayl ham "hash'li" ko'rinishi mumkin. Haqiqiy vositalar buning uchun Vite'ning build.manifest faylidan (.vite/manifest.json — manba → chiqish nomi) foydalanadi.
4-mashq: Amaliy tajriba — vazifalar da o'lchov
Bu darsda vazifalar kodi o'zgarmaydi. O'z loyihangizda:
npm run buildchiqishidan chunk'larni sanang. Qaysi biri dinamik?src/dagi bitta faylga izoh qo'shib, qayta build qiling. Qaysi hash'lar o'zgardi? Izoh minifikatsiyada o'chadi — natija sizni ajablantiradimi?git restorebilan qaytaring.
Yechim
- Ikki JS chunk +
tema.js:index-….js(entry) vaolchov-….js(dinamik,import("./olchov.ts")).tema.js— alohida entry, hash'siz nom (ataylab). - Faqat izoh qo'shilsa — hech qaysi hash o'zgarmaydi: minifikatsiyadan keyin tarkib bir xil. Lekin
build.sourcemap: truebo'lgani uchun.mapfayl o'zgaradi (undasourcesContent— asl matn). Hash JS tarkibidan hisoblanadi, xaritadan emas. Foydalanuvchi uchun hech narsa qayta yuklanmaydi. git status— toza.
9. Real ishda
- Katta SPAlarda (React, Vue) route-level code splitting — standart: har sahifa o'z chunk'i, umumiy kutubxonalar — vendor.
- "Ba'zi foydalanuvchilarda tugma ishlamayapti" degan shikoyat kelsa — birinchi gumon: eski chunk. Sentry'da
Failed to fetch dynamically imported module— eng ko'p uchraydigan xatolardan biri. - Intervyu savollari: "Code splitting nima?", "Content hash nima uchun?", "
immutablevano-cachefarqi?", "Deploydan keyin chunk 404 bo'lsa nima qilasiz?".
Xulosa
- Dinamik
import()— alohida chunk; vendor chunk (codeSplitting.groups) — kam o'zgaradigan kutubxonalar alohida. Kichik bo'laklar zarar: ko'p so'rov. - Content hash tarkibdan: o'zgarsa — yangi nom. Hash zanjiri import yo'nalishi bo'yicha tarqaladi; vendor ilova kodini import qilmagani uchun keshda qoladi.
- Hash'li fayllar —
max-age=31536000, immutable;index.html—no-cache. Pages'da hammasimax-age=600. modulepreload— statik bog'liq chunk'larni oldindan yuklash; dinamik importlar uchun Vite'ning preload yordamchisi.- Eski chunk xatosi (
Failed to fetch dynamically imported module):.catch,vite:preloadError→location.reload(), eski fayllarni serverda qoldirish.
Keyingi dars: Vite I: nega tez va loyiha yaratish — npm create vite bilan loyiha, dev server nega bir zumda ishga tushishi, HMR va vazifalar ga npm run dev va npm run preview.
Manbalar
- Vite: "Building for Production → Chunking Strategy", "Load Error Handling" (
vite:preloadError) — vite.dev/guide/build - Rolldown: "Code Splitting",
output.codeSplitting— rolldown.rs - MDN: "Cache-Control" (
immutable,no-cache) — developer.mozilla.org/docs/Web/HTTP/Headers/Cache-Control - web.dev: "Prefer HTTP caching", "Preload modules" — web.dev
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!