IlmHamroh
JavaScript Full-stack/16-qism. Frontend asboblari: npm, bundlerlar, config29/48-dars17 daqiqa
Mundarija (35)

Vite IV: assetlar, public papka va maxsus importlar

Qisqacha: Vite'da rasm, shrift, CSS va JSON ham modul. Masalan, import logo from "./logo.png" manzil (URL) qaytaradi, fayl esa build'da hash'li nom oladi. Kichik (4 KB gacha) fayl esa data: satr bo'lib kodga qo'shiladi. Maxsus qo'shimchalar: ?raw — fayl matni, ?inline — har doim data:, ?worker — Web Worker. Funksiya import.meta.glob bir papkadagi ko'p faylni bir yo'la oladi. Papka public/ dagi fayllar esa qayta ishlanmaydi — dist/ ga o'z nomi bilan ko'chadi.

Bu darsda

  • src/ dagi asset bilan public/ dagi fayl farqini va qaysini qachon tanlashni bilasiz.
  • Rasm, JSON va CSS'ni import qilasiz va build'da ular nimaga aylanishini ko'rasiz.
  • ?url, ?raw, ?inline, ?no-inline, ?worker so'rov qo'shimchalarini ishlatasiz.
  • import.meta.glob bilan papkadagi fayllarni yig'asiz; CSS Modules va Sass'ni ulaysiz.
  • vazifalar manbasini src/ ga ko'chirasiz.

Oldin bilishingiz kerak: Vite III: env va rejimlar, Bundler nima: chunk va asset, CSS Modules, Declaration fayllari.

1. Nega bu kerak?

Jasur aka menyuga taom rasmlarini qo'shmoqchi. Sardor odatdagidek yozdi: <img src="rasmlar/osh.png">. Sahifa ishladi. Keyin u rasmni yangiladi — fayl nomi o'sha. Mijozlarning telefonida eski rasm qoldi: brauzer keshi osh.png ni "o'zgarmagan" deb hisobladi.

JavaScript va CSS'da bu muammoni hash hal qilgan edi (Code splitting va hash): tarkib o'zgarsa — nom o'zgaradi. Rasm uchun ham shunday bo'lishi mumkin. Lekin buning uchun Vite rasmni "bilishi" kerak — ya'ni u import grafida bo'lishi kerak.

Ikkinchi muammo — vazifalar loyihasining tuzilmasi. Manba assets/js/*.ts da, ikonlar public/assets/ikonlar/ da, CSS assets/css/ da. assets so'zi ikki joyda, ikki ma'noda. Vite va React loyihalarining umumiy odati boshqacha: manba — src/, o'zgarmas fayllar — public/. 17-qismda React shu tuzilmani kutadi. Bugun ko'chamiz.

Oshxona o'xshatishi: src/ — oshxona ichidagi mahsulotlar, ular oshpaz (Vite) qo'lidan o'tadi: to'g'raladi, pishiriladi, yorliq oladi. public/ — zaldagi stullar va idishlar: oshpaz ularga tegmaydi, ular qanday bo'lsa, shunday qoladi.

2. Asset — modul sifatida

2.1 Rasmni import qilish

Asset — kod bo'lmagan, lekin saytga kerak fayl: rasm, shrift, video, ikonka. Vite'da asset'ni JavaScript'dan import qilish mumkin. Sardorning tajriba fayli src/assets.ts:

ts
import iconUrl from "./assets/ikon.svg";
import logoUrl from "./assets/ikon-512.png";

console.log("svg:", iconUrl.slice(0, 40));
console.log("png:", logoUrl);

import dan nima keladi? Rasmning o'zi emas — uning manzili (satr). Uni <img src> ga yoki CSS'ga berasiz. Build natijasi:

text
✓ 15 modules transformed.
dist/index.html                    0.43 kB │ gzip: 0.28 kB
dist/assets/ikon-512-BbD8f31g.png  7.51 kB
dist/assets/index-DxwH6dRG.css     0.15 kB │ gzip: 0.14 kB
dist/assets/dushanba-B1ucG8bk.js   0.03 kB │ gzip: 0.05 kB
dist/assets/seshanba-BDdDn3RT.js   0.03 kB │ gzip: 0.05 kB
dist/assets/index-BFQ07-nt.js      3.39 kB │ gzip: 1.70 kB

(dushanba va seshanba — pastdagi import.meta.glob misolidan.) PNG — ikon-512-BbD8f31g.png: nom + hash. SVG esa ro'yxatda yo'q. JS fayl ichida qidirdik:

text
var n=`data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2032%2032'…
…r=`/assets/ikon-512-BbD8f31g.png`
  • logoUrl — "/assets/ikon-512-BbD8f31g.png": hash'li fayl manzili. Rasm o'zgarsa, hash o'zgaradi va kesh muammosi yo'qoladi.
  • iconUrl — data:image/svg+xml,…: SVG faylning o'zi, satr ichida. Alohida fayl yo'q, alohida so'rov ham yo'q.

2.2 assetsInlineLimit — 4 KB chegara

Nega biri fayl, biri satr? SVG — 275 bayt, PNG — 7 514 bayt. Vite'da build.assetsInlineLimit sozlamasi bor, sukut bo'yicha 4096 bayt (Vite II dagi jadval). Undan kichik asset inline qilinadi — data: URL bo'lib JS yoki CSS ichiga qo'shiladi.

Nega? Har alohida fayl — alohida HTTP so'rov. 275 baytlik ikonka uchun so'rovning o'zi (sarlavhalar, kutish) fayldan qimmatroq. Katta fayl esa inline qilinsa, JS'ni og'irlashtiradi va alohida keshlanmaydi. 4 KB — o'rtacha murosa.

flowchart TB
  A["src/ dagi asset<br/>(import qilingan)"] --> B{"4 KB dan<br/>kichikmi?"}
  B -- ha --> C["data: URL<br/>JS ichida"]
  B -- yo'q --> D["assets/nom-HASH.png"]
  P["public/ dagi fayl"] --> Q["dist/ ga<br/>o'z nomi bilan"]

Diagrammaning o'ng tomoniga e'tibor bering: public/ yo'li hech qanday tekshiruvdan o'tmaydi. Buni keyingi bo'limda ochamiz.

assetsInlineLimit: 0 — hech narsani inline qilmaslik. Bu qachon kerak? Masalan, saytda qattiq CSP bo'lsa va img-src da data: ruxsat etilmagan bo'lsa (XSS va DOM xavfsizligi).

2.3 TypeScript .svg ni qayerdan biladi

Declaration fayllari darsida import logo from "./logo.svg" uchun TS2307 xatosini ko'rib, declare module "*.svg" yozgan edik va "Vite shablonlari buni tayyor beradi" degan edik. Mana u: npm create vite shablonining tsconfig.json ida "types": ["vite/client"] bor, vite/client esa *.svg, *.png, *.module.css, ?raw, ?worker kabi yuzlab shakl uchun turni e'lon qilgan. Shuning uchun Sardorning fayli tsc --noEmit dan toza o'tdi.

Tekshirib ko'ring: 3 KB lik chiziq.png va 30 KB lik taom.jpg import qilindi. Build'dan keyin dist/assets/ da nechta rasm fayli bo'ladi?

Javob

Bitta — taom-<hash>.jpg. chiziq.png 4096 baytdan kichik, u data:image/png;base64,… satri bo'lib JS ichiga tushadi. Agar ikkala rasm faqat CSS'da (background: url(./chiziq.png)) ishlatilsa — inline satr CSS faylga tushadi.

3. public/ papka

3.1 Qayta ishlanmaydigan fayllar

public/ dagi har fayl build'da dist/ ning ildiziga o'z nomi bilan, o'zgarishsiz ko'chadi. Hash yo'q, siqish yo'q, import grafi yo'q. Ularga import bilan emas, manzil bilan murojaat qilinadi: public/favicon.svg → /favicon.svg (yoki base bilan).

Qaysi fayllar public/ ga?

Fayl Nega public/
favicon.ico, robots.txt brauzer va qidiruv tizimi aniq nom bilan so'raydi
sw.js Service Worker manzili o'zgarmasligi kerak
manifest.webmanifest va ikonlar manifest ichidagi yo'llarni Vite qayta yozmaydi
katta video, PDF kodda import qilinmaydi, havola bilan beriladi

Qolgan hamma narsa (komponent rasmlari, shriftlar, CSS) — src/ da, import bilan.

3.2 vazifalar dagi haqiqiy saboq

vazifalar da public/ ni Bundler nima darsida yaratgan edik. Esingizdami, nega? Birinchi urinishda public/ siz Vite manifest va ikonlarni ham asset deb hash'ladi:

text
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 kB

Manifest nomi o'zgardi — index.html dagi havola Vite tomonidan yangilandi. Lekin manifest ichidagi ikon yo'llari ("assets/ikonlar/ikon-192.png") eskicha qoldi — Vite JSON ichini tushunmaydi. sw.js esa dist/ ga umuman tushmadi: uni hech kim import qilmaydi. Yechim — uchalasi public/ ga. Bu qoida: nomi tashqi dunyo uchun muhim bo'lgan fayl — public/ da.

3.3 public/ dagi faylni import qilmang

public/ fayl uchun manzil yetarli: <img src="/favicon.svg">. Uni import x from "../public/favicon.svg" deb import qilish — ikki marta ko'chirish va adashtirish yo'li. Vite hujjatlari ham buni tavsiya qilmaydi.

Tekshirib ko'ring: src/ dagi logo.png ni index.html da <img src="/src/logo.png"> deb yozdingiz (import'siz). Build'da nima bo'ladi?

Javob

Vite index.html ni ham o'qiydi — u import grafining boshi. HTML'dagi src, href dagi mahalliy fayllarni u asset deb biladi va build'da hash'li manzil bilan almashtiradi (yoki kichik bo'lsa inline qiladi). Shuning uchun bu ishlaydi. public/ dagi fayl (/favicon.svg) esa tegilmaydi — Vite uni public/ da topadi va manzilni o'zgarishsiz qoldiradi.

4. Maxsus importlar: ? qo'shimchalari

Import yo'lining oxiriga ?nom qo'shib, Vite'ga "bu faylni boshqacha ber" deyish mumkin. Bu — Vite'ning o'z kelishuvi, brauzer standarti emas.

Yozuv Nima qaytaradi
./ikon.svg manzil; kichik bo'lsa — data:
./ikon.svg?url xuddi shunday manzil (aniq yozilgan)
./ikon.svg?no-inline har doim alohida fayl manzili
./ikon-512.png?inline har doim data: (katta bo'lsa ham)
Yozuv Nima qaytaradi
./ikon.svg?raw fayl matni (satr)
./hisob.worker.ts?worker Worker yasaydigan klass
./narxlar.json JSON obyekti

Hammasi sinaldi. Diqqatga sazovor natijalar:

  • ?url — Vite 8.3.3 da kichik SVG uchun baribir data: qaytardi. Ya'ni ?url "faylga aylantir" degani emas. Alohida fayl majburan kerak bo'lsa — ?no-inline: shunda dist/assets/ikon-CdIzd46i.svg paydo bo'ldi.
  • ?inline — 7.5 KB PNG data:image/png;base64,iVBORw0KGgo… bo'lib JS ichiga tushdi. Natijada index chunk 3.39 kB dan 14.04 kB ga o'sdi: base64 faylni taxminan uchdan bir qism kattalashtiradi.
  • ?raw — SVG matni satr bo'lib keldi (raw.length — 275). SVG'ni HTML'ga to'g'ridan-to'g'ri qo'yish (SVG va ikonka pipeline darsida) uchun kerak.

4.1 JSON import va tree shaking

ts
import { osh } from "./narxlar.json";

JSON — Vite uchun modul: har yuqori darajadagi kalit — alohida eksport. Biz faqat osh ni oldik, build'da faqat shu qoldi: a=35e3 (35e3 — 35 000). lagmon, manti, choy kalitlari JS'ga umuman tushmadi — tree shaking JSON'da ham ishlaydi. Butun obyekt kerak bo'lsa — import narxlar from "./narxlar.json".

4.2 Web Worker

Web Workers darsida "Vite kabi bundler'lar new Worker(new URL("./w.js", import.meta.url)) yozuvini tushunadi" degan edik. Ikki usulni ham sinadik:

ts
import HisobWorker from "./hisob.worker.ts?worker";

const w1 = new HisobWorker();
const w2 = new Worker(new URL("./hisob.worker.ts", import.meta.url), {
  type: "module",
});

Build'da worker alohida fayl bo'ldi — dist/assets/hisob.worker-CHGW98Gp.js — va ikkala yozuv ham shu manzilni oldi:

text
return new Worker(`/assets/hisob.worker-CHGW98Gp.js`,{name:e?.name})
g=new Worker(new URL(`/assets/hisob.worker-CHGW98Gp.js`,``+import.meta.url),{type:`module`})

Ikkinchi usul — standart JavaScript, Vite'siz ham ma'noli; shuning uchun ko'p loyiha uni afzal ko'radi. Worker ichida TypeScript ham ishlaydi — Vite uni ham o'giradi.

4.3 import.meta.glob — papkani bir yo'la olish

Menyu har kun uchun alohida faylda: src/kunlar/dushanba.ts, seshanba.ts… Har birini qo'lda import qilish — har yangi kunda kodni o'zgartirish. import.meta.glob buni build vaqtida qiladi:

ts
const days = import.meta.glob("./kunlar/*.ts");
console.log("glob:", Object.keys(days));

Glob — * kabi belgilar bilan fayl nomlari naqshi (.gitignore dagi kabi). Natija — obyekt: kalit — fayl yo'li, qiymat — o'sha faylni yuklaydigan funksiya. Build ichida:

text
{"./kunlar/dushanba.ts":()=>d(()=>import(`./dushanba-B1ucG8bk.js`),[]),"./kunlar/seshanba.ts":…

Har fayl — alohida chunk va dinamik import(): faqat chaqirilganda yuklanadi. Hammasi darhol kerak bo'lsa — { eager: true }: fayllar asosiy chunk'ka qo'shiladi va qiymat — modulning o'zi. Buni 3-mashqda qilasiz.

E'tibor bering: bu Vite'ning (va boshqa bundler'larning) kengaytmasi. Node'da import.meta.glob yo'q — node --test bilan sinaladigan modulda ishlatmang.

Tekshirib ko'ring: import.meta.glob("./kunlar/*.ts") dagi naqshni o'zgaruvchidan olsa bo'ladimi: const p = "./kunlar/*.ts"; import.meta.glob(p)?

Javob

Yo'q. Vite naqshni build vaqtida kodni o'qib topadi va fayllar ro'yxatini o'sha joyga yozib qo'yadi. O'zgaruvchining qiymati faqat ishga tushganda ma'lum bo'ladi — Vite uni bilmaydi. Shuning uchun argument — faqat oddiy satr literal. Xuddi define va import.meta.env kabi: Vite kodni matn sifatida o'qiydi.

5. CSS: import, CSS Modules, Sass

5.1 CSS Modules

CSS Modules darsida natijalarni "biz Vite 8.3.1 da build qilib oldik" degan edik. Endi o'zingiz qila olasiz. .module.css bilan tugaydigan fayl — CSS Module:

ts
import styles from "./menyu.module.css";
console.log("css:", styles.card, styles.price);

Build'da JS ichida o={card:"_card_3g10o_1",price:"_price_3g10o_5"}, CSS faylda esa:

text
._card_3g10o_1{border:1px solid #1f6f4a;padding:.5rem}._price_3g10o_5{font-weight:700}

Klass nomlari noyob bo'ldi — boshqa fayldagi .card bilan to'qnashmaydi. Kodda esa siz styles.card deb yozasiz.

5.2 Sass

Vite .scss ni taniydi, lekin Sass kompilyatorini o'zi bilan olib yurmaydi. src/sarlavha.scss ni import qilib, dev serverni ochdik:

text
[vite] Internal server error: Preprocessor dependency "sass-embedded" not found. Did you install it? Try `npm install -D sass-embedded`.
  Plugin: vite:css

Tarjimasi: "sass-embedded preprotsessor bog'liqligi topilmadi. O'rnatdingizmi?". Xabar yechimni ham aytadi. npm i -D sass-embedded (2026-10 holatiga 1.105.1) dan keyin build'da $rang o'zgaruvchisi o'z qiymatiga aylandi: h1{color:#1f6f4a}. Narxi — node_modules ga ~16 MB (Windows binari bilan). Sass darslari dagi hamma narsa Vite'da sozlamasiz ishlaydi.

5.3 CSS'ni JS'dan import qilish — dev'dagi tuzoq

Vite loyihalarida ko'pincha import "./style.css" yoziladi. Build'da bu oddiy <link rel="stylesheet"> bo'ladi. Dev'da esa Vite CSS'ni <style> tegi qilib qo'shadi (HMR uchun qulay). vazifalar da shu sinab ko'rildi — dev'da sahifa uslubsiz chiqdi:

text
Applying inline style violates the following Content Security Policy directive 'style-src 'self''. Either the 'unsafe-inline' keyword, a hash ('sha256-gQkjxiOevwCGQsNGnxIAwREte6R0DsvVMiiTUrkCbjw='), or a nonce ('nonce-...') is required to enable inline execution. The action has been blocked.

Tarjimasi: "Inline uslubni qo'llash CSP'ning style-src 'self' qoidasini buzadi... amal to'sildi". Bizning CSP inline uslubni taqiqlaydi (XSS va DOM xavfsizligi). Shuning uchun vazifalar da CSS index.html dagi <link> orqali ulanadi — dev'da ham, build'da ham fayl bo'lib keladi. CSP'siz loyihada (masalan, 17-qismdagi React shabloni) import "./style.css" — odatiy yo'l.

Bu tajriba yana bir muhim narsani ko'rsatadi: dev va build bir xil emas. Dev server — tez ishlash uchun soddalashtirilgan yo'l (CSS — <style>, define — global o'zgaruvchi, fayllar — alohida modul). Build — saytga chiqadigan haqiqiy natija. Shuning uchun deploydan oldin har doim npm run build va npm run preview bilan tekshiring: dev'da ishlagan narsa build'da buzilishi mumkin, aksincha ham.

Tekshirib ko'ring: Sardor vazifalar da CSS'ni import "./vazifalar.css" ga o'tkazdi. npm run build va npm run preview da sahifa chiroyli. Hamma narsa joyidami?

Javob

Yo'q. Build'da Vite CSS'ni alohida fayl qilib <link> bilan ulaydi — CSP'ga mos, shuning uchun preview'da muammo ko'rinmaydi. Lekin npm run dev da CSS <style> tegi bo'lib keladi va CSP uni to'sadi: dasturchi uslubsiz sahifada ishlaydi. Ikkala rejimni ham tekshirish kerak — vazifalar dagi brauzer tekshiruvi aynan shuning uchun dev'da ham ishga tushiriladi.

6. Vazifalar qadami: manba src/ ga

Branch: refactor/src-public

6.1 Ko'chirish

git mv — faylni ko'chiradi va Git'ga "bu o'sha fayl, faqat nomi boshqa" deydi (tarix saqlanadi):

bash
git switch -c refactor/src-public
git mv assets/js src
git mv assets/css/vazifalar.css src/

assets/js papkasi butunligicha src bo'ldi (21 fayl: 19 ta .ts va 2 ta .d.ts), CSS unga qo'shildi. assets/ papkasi bo'shab, yo'qoldi. public/ — Bundler nima dan beri joyida.

6.2 Yo'llarni yangilash

Ko'chgan fayllarga ishora qiladigan har joy:

Fayl Nima o'zgardi
index.html href="src/vazifalar.css", src="src/asosiy.ts"
tsconfig.json "include": ["src"] (izohda ham)
eslint.config.js uchta files: "src/**/*.ts", "src/**/*.{js,ts}"
tekshiruv/*.test.js from "../src/…" (14 fayl)
Fayl Nima o'zgardi
vite.config.ts input.tema: "src/tema.ts" va resolve.alias (pastda)
src/tema.ts sarlavha izohi: endi uni Vite yozadi, tsc emas

Testlardagi importlarni bitta buyruq bilan almashtirish mumkin (Git Bash):

bash
sed -i 's#\.\./assets/js/#../src/#' tekshiruv/*.js

sed -i — fayl ichidagi matnni almashtiradigan terminal buyrug'i: har faylda ../assets/js/ ni ../src/ ga almashtiradi. # — ajratgich (yo'lda / ko'p bo'lgani uchun).

6.3 Dev'dagi 404 va resolve.alias

npm run build — toza. npm run dev da esa bitta xato:

text
404 /assets/js/tema.js
error: Failed to load resource: the server responded with a status of 404 (Not Found)

Nega? index.html dagi <script src="assets/js/tema.js"> — oddiy skript (modul emas, Bundler nima da tushuntirilgan). Build'da tema.ts alohida kirish nuqtasi bo'lib shu nom bilan yoziladi. Dev'da esa build yo'q — Vite diskdan assets/js/tema.js ni qidiradi. Avval u assets/js/tema.ts ni topar edi (Vite I da .js → .ts ni o'zi topgan edi). Endi fayl src/ da.

Yechim — oldingi darsdan tanish resolve.alias:

ts
resolve: {
  alias: {
    // npm run dev: index.html dagi <script src="assets/js/tema.js">
    // ni src/tema.ts ga yo'naltiramiz (Vite uni JS qilib beradi).
    // Build'da kerak emas — u yerda tema.js shu nom bilan yoziladi
    "/assets/js/tema.js": "/src/tema.ts",
  },
},

Endi dev'da 200 /assets/js/tema.js (Content-Type: text/javascript). HTML va sayt manzillari o'zgarmadi — eski URL'lar (va CSP) bir harf ham buzilmadi.

6.4 Natija: hech narsa o'zgarmadi — va bu yaxshi

text
dist/assets/index-BI1hyTgJ.css   3.59 kB │ gzip: 1.29 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

Hash'lar oldingi qadam bilan bayt-bayt bir xil: index-Dvsf2Sj6.js, index-BI1hyTgJ.css. Faqat source map biroz qisqardi (115.43 → 115.33 kB) — undagi yo'llar qisqa bo'ldi (assets/js/ → src/). 41 ta fayl o'zgardi, sayt esa o'sha-o'sha. Refaktoringning ideal natijasi.

npm run check da bitta topilma: prettier — qidiruv.test.js dagi import yo'l qisqargach bir qatorga sig'adi. npx prettier --write tekshiruv/qidiruv.test.js — tuzaldi. Testlar 145/145, brauzer tekshiruvi 159/159.

bash
git add .
git commit -m \
"refactor: manba src/ ga ko'chdi; dev'da tema.js — resolve.alias"

7. Ko'p uchraydigan xatolar

7.1 public/ dagi faylga src/ yo'li bilan murojaat

<img src="/public/logo.png"> — xato: public/ papka nomi manzilga kirmaydi. To'g'risi — /logo.png. Build'dan keyin dist/public/ umuman yo'q.

7.2 base ni unutish

/logo.png — base: "/" uchun. Sayt /bahor-menyu/ da bo'lsa, public/ fayllariga JS'da import.meta.env.BASE_URL + "logo.png" bilan murojaat qiling (Vite III dagi BASE_URL). HTML'dagi manzillarni Vite o'zi to'g'rilaydi, JS satrlaridagini — yo'q.

7.3 Dinamik nom bilan import

import(`./rasmlar/${nom}.png`) — Vite qaysi fayllarni olishni bilmaydi. Variantlar oldindan ma'lum bo'lsa — import.meta.glob("./rasmlar/*.png", { eager: true, import: "default" }) va nom bo'yicha tanlash.

7.4 Sass o'rnatilmagan

Preprocessor dependency "sass-embedded" not found — npm i -D sass-embedded.

8. Mashqlar

Mashqlar kurs/mashqlar/16/29-assetlar/ da — Vite II dagi bahor-menyu nusxasi.

1-mashq (oson): src/ mi, public/ mi?

  1. robots.txt —
  2. Menyu kartasidagi osh.png (TS'dan import) —
  3. manifest.webmanifest —
  4. Sarlavha shrifti Inter.woff2 (CSS'dagi @font-face) —
  5. Service Worker sw.js —
Yechim

1, 3, 5 — public/: ularni brauzer yoki tizim aniq nom bilan so'raydi. 2 va 4 — src/: Vite ularni hash'laydi (yoki inline qiladi), shrift yangilansa kesh muammosi bo'lmaydi.

2-mashq (o'rta): Rasm, JSON va CSS Module

  1. src/assets/osh.svg (kichik ikonka) va src/assets/bahor.png (4 KB dan katta logotip) qo'ying.
  2. src/narxlar.json — { "osh": 35000, "lagmon": 28000, "manti": 30000, "choy": 5000 }.
  3. src/karta.module.css — .card va .price klasslari.
  4. main.ts: ikonka + "Osh — 35 000 so'm" kartasi (narx JSON'dan, nomlangan import bilan), sahifa boshida logotip.
  5. npx vite build — dist/ da nechta rasm? lagmon so'zi JS'ga tushdimi?
Yechim
ts
import "./style.css";
import oshIcon from "./assets/osh.svg";
import logo from "./assets/bahor.png";
import { osh } from "./narxlar.json";
import styles from "./karta.module.css";
import { formatPrice } from "./menyu.ts";

const card = document.createElement("div");
card.className = styles.card;
card.innerHTML = `<img src="${oshIcon}" width="32" alt="">
  <span>Osh — <b class="${styles.price}">
  ${formatPrice(osh)}</b></span>`;
document.body.append(card);

const header = document.createElement("img");
header.src = logo;
header.alt = "«Bahor» logotipi";
header.width = 64;
document.body.prepend(header);

innerHTML bu yerda xavfsiz: hamma qiymat o'zimizniki, foydalanuvchi matni yo'q (XSS darsidagi qoida — begona matn faqat textContent).

Build:

text
✓ 13 modules transformed.
dist/index.html                 0.49 kB │ gzip: 0.31 kB
dist/assets/bahor-BbD8f31g.png  7.51 kB
dist/assets/index-DzxXSKe-.css  0.16 kB │ gzip: 0.14 kB
dist/assets/index-aunmUmsI.js   1.78 kB │ gzip: 1.00 kB

Rasm fayli bitta — bahor-….png; osh.svg JS ichida data:image/svg+xml,… bo'lib qoldi. lagmon — 0 marta: JSON'dan faqat osh olindi.

3-mashq (qiyin): Haftalik menyu — import.meta.glob

src/kunlar/ da uch fayl: dushanba.ts — export const dish = "Osh";, seshanba.ts — "Lag'mon", chorshanba.ts — "Manti". Sahifaga ro'yxat chiqaring: har kun alohida <li>, masalan dushanba: Osh. Yangi kun fayli qo'shilsa, main.ts o'zgarmasin.

Ishora: import.meta.glob<string>(naqsh, { eager: true, import: "dish" }) — eager fayllarni darhol qo'shadi, import: "dish" har moduldan faqat dish eksportini oladi. Object.entries — kalit va qiymat juftlari.

Yechim
ts
// hamma kun fayli build vaqtida yig'iladi
const days = import.meta.glob<string>("./kunlar/*.ts", {
  eager: true,
  import: "dish",
});
const week = document.createElement("ul");
for (const [path, dish] of Object.entries(days)) {
  const day = path.replace("./kunlar/", "").replace(".ts", "");
  const item = document.createElement("li");
  item.textContent = `${day}: ${dish}`;
  week.append(item);
}
document.body.append(week);

Build ichida (bir bo'lak):

text
{"./kunlar/chorshanba.ts":e,"./kunlar/dushanba.ts":`Osh`,"./kunlar/seshanba.ts":t}

Alohida chunk yo'q — eager hammasini asosiy faylga qo'shdi. Kalitlar alifbo tartibida (chorshanba birinchi): kunlar tartibi kerak bo'lsa, fayl nomiga raqam qo'shing (1-dushanba.ts) yoki tartib ro'yxatini alohida yozing. <string> — qiymat turini TypeScript'ga aytadi.

9. Real ishda

  • Har React/Vue loyihada rasm va ikonkalar import qilinadi, public/ da esa faqat favicon, robots.txt, manifest. Kod tekshiruvida "nega bu rasm public/ da?" — odatiy savol.
  • Rasm optimizatsiyasi — katta loyihalarda rasmlar build vaqtida siqiladi va bir nechta o'lchamga bo'linadi (masalan, vite-imagetools plagini). Vite buni o'zi qilmaydi: u rasmni faqat nomlaydi va ko'chiradi. Rasm hajmini kamaytirish — sizning ishingiz (Rasm unumdorligi darsidagi formatlar va srcset).
  • import.meta.glob — fayl asosidagi marshrutlar, tarjima fayllari (locales/*.json), blog maqolalari uchun keng ishlatiladi.
  • Intervyu savollari: "public/ va src/assets/ farqi?", "Nega kichik rasmlar inline qilinadi?", "Rasmni yangilasam, foydalanuvchida eskisi qolmasligini qanday ta'minlaysiz?".

Xulosa

  • src/ dagi import qilingan asset — hash'li fayl yoki (4096 baytdan kichik bo'lsa) data: URL; public/ dagi fayl — dist/ ga o'zgarishsiz.
  • Nomi tashqi dunyo uchun muhim fayl (sw.js, manifest, robots.txt) — public/ da.
  • ?raw — matn, ?inline — har doim data:, ?no-inline — har doim fayl, ?worker — Worker; ?url kichik faylni baribir inline qiladi.
  • JSON nomlangan import bilan tree shaking'dan o'tadi; import.meta.glob papkani build vaqtida yig'adi (literal naqsh bilan).
  • CSS Modules sozlamasiz, Sass — sass-embedded bilan; dev'da import qilingan CSS <style> bo'ladi (CSP bilan to'qnashadi).
  • vazifalar: manba src/ da, hash'lar o'zgarmadi, dev'da tema.js — resolve.alias.

Keyingi dars: Vite V: production build va bundle tahlili — build chiqishini o'qish, chunk'larni bo'lish va npm run analiz bilan "qaysi modul qancha joy egallaydi?" savoliga javob; Zod'ni o'lchab qaror qilamiz.

Manbalar

  • Vite hujjatlari: "Static Asset Handling" (?url, ?raw, ?inline, ?no-inline, public/) — vite.dev/guide/assets
  • Vite hujjatlari: "Features" — JSON, Glob Import, Web Workers, CSS Modules, CSS Pre-processors — vite.dev/guide/features
  • Vite 8.3.3, sass-embedded 1.105.1 — darsdagi build chiqishlari 2026-10 da olingan
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Vite IV: assetlar, public papka va maxsus importlar — IlmHamroh