Mundarija (26)
- Bu darsda
- 1. Nega bu kerak?
- 2. Import qilingan rasm
- 2.1 import — satr qaytaradi
- 2.2 Build natijasi
- 2.3 TypeScript va rasm importi
- 3. Ma'lumotdan rasm
- 3.1 Muammo: manzil satrda
- 3.2 public/ va base
- 4. SVG — komponent sifatida
- 4.1 <img> yoki JSX ichida
- 4.2 SVG atributlari — camelCase
- 4.3 vite-plugin-svgr — ?react import
- 5. <img> — to'g'ri atributlar
- 5.1 alt
- 5.2 width, height va sakrash
- 5.3 loading="lazy" va fetchPriority
- 6. Vazifalar: ikonkalar public/ da
- 7. Ko'p uchraydigan xatolar
- 8. Mashqlar
- 1-mashq (oson): Qayerga qo'yish kerak?
- 2-mashq (o'rta): Ikonka komponenti
- 3-mashq (qiyin): Rasmli menyu — Vite loyihada
- 9. Real ishda
- Xulosa
- Manbalar
Rasm, SVG va assetlar React komponentlarida: import, public va alt
Qisqacha: React'da rasm ikki yo'l bilan ulanadi. Import —
import oshUrl from "./assets/osh.webp": Vite faylni build'ga qo'shadi, nomiga hash yozadi (osh-Czri_yu8.webp), 4 KB dan kichigini esadata:URL qilib JS ichiga joylaydi;oshUrl— oddiy satr,<img src={oshUrl}>.public/papka — fayl o'zgarishsiz nusxalanadi, manzil qo'lda yoziladi (src="/rasmlar/manti.webp"). SVG ikonka uchun eng qulayi — JSX'dagi<svg>komponent (atributlar camelCase:strokeWidth), rang —currentColor. Har<img>gaalt(bezak bo'lsa —alt=""),widthvaheight(sahifa sakramasin), pastdagi rasmlargaloading="lazy".
Bu darsda
- Import qilingan rasm va
public/papkadagi rasm farqini Vite build natijasida ko'rasiz. - Ma'lumotdan (menyu ro'yxati) rasm manzilini to'g'ri yasaysiz.
- SVG'ni React komponentiga aylantirasiz: props bilan o'lcham va rang, kirish imkoniyati.
vite-plugin-svgr(?react) va sprite usullarining React'dagi ko'rinishini bilasiz.alt,width/height,loading,fetchPriorityni to'g'ri yozasiz.
Oldin bilishingiz kerak: Vite IV: assetlar va public papka, SVG va ikonka pipeline, Yaxshi alt matn yozish, React'da stil berish.
1. Nega bu kerak?
«Bahor» menyusida endi har taomning surati bo'lishi kerak. Sardor rasmlarni src/rasmlar/ ga qo'ydi va yozdi: <img src="./rasmlar/osh.webp">. Dev serverda ishladi. Build qilib GitHub Pages'ga qo'ydi — hamma rasm o'rnida singan belgi.
Sabab: src/ dagi fayllar build'da o'zgaradi. Ular yig'iladi, nomi hash bilan almashadi, dist/ da src/rasmlar/ degan papka umuman yo'q. Satrda yozilgan "./rasmlar/osh.webp" ni Vite rasm deb tanimaydi — u oddiy matn. Vite faqat import qilingan yoki public/ da turgan fayllarni biladi.
Vite IV darsida bu qoidani HTML va CSS uchun ko'rgansiz. Bugun uni React komponentlarida qo'llaymiz va yana uch narsani qo'shamiz: SVG ikonkalarni komponent qilish, alt matn va sahifa sakramasligi.
Hayotiy o'xshatish: oshxonaga ziravor buyurtma qilish. Ro'yxatga yozilgan (import) ziravorni omborchi oladi, yorliq yopishtiradi va kerakli javonga qo'yadi. Ro'yxatda yo'q, lekin oshpaz "u yerda turibdi" deb og'zaki aytgan ziravorni hech kim olib kelmaydi. public/ esa ochiq javon — u yerdagini omborchi tekshirmaydi, borligicha qo'yadi.
2. Import qilingan rasm
2.1 import — satr qaytaradi
import oshUrl from "./assets/osh.webp";
import qalampirUrl from "./assets/qalampir.svg";
export default function App() {
return (
<main>
<img
src={oshUrl}
alt="Osh: guruch, sabzi va go'sht"
width={480}
height={320}
/>
<img src={qalampirUrl} alt="" width={16} height={16} />
<img
src="/rasmlar/manti.webp"
alt="Manti"
width={480}
height={320}
/>
</main>
);
}oshUrl — rasmning o'zi emas, uning manzili (satr). Rasm JS'ga kirmaydi; JS faqat manzilni biladi. Uchinchi rasm esa public/rasmlar/manti.webp da turibdi va manzili qo'lda yozilgan.
2.2 Build natijasi
Birinchi React loyiha darsidagi bahor-menyu ga uchta fayl qo'shildi: src/assets/osh.webp (11 046 bayt), src/assets/qalampir.svg (147 bayt) va public/rasmlar/manti.webp. Build (Vite 8.3.4, 2026-10-13):
npx vite buildChiqishda uch faylni qidiring: osh rasmi bormi, qalampir bormi, manti bormi?
vite v8.3.4 building client environment for production...
transforming...
✓ 19 modules transformed.
rendering chunks...
computing gzip size...
dist/index.html 0.50 kB │ gzip: 0.33 kB
dist/assets/osh-Czri_yu8.webp 11.04 kB
dist/assets/index-DGNrK5qb.css 1.78 kB │ gzip: 0.81 kB
dist/assets/index-C63bVS3p.js 220.31 kB │ gzip: 68.99 kB
✓ built in 136msUch xil taqdir:
| Fayl | dist/ da |
JS ichida src |
|---|---|---|
src/assets/osh.webp (11 KB) |
assets/osh-Czri_yu8.webp |
`/assets/osh-Czri_yu8.webp` |
src/assets/qalampir.svg (147 B) |
yo'q! | `data:image/svg+xml,%3csvg%20xmlns=…` |
public/rasmlar/manti.webp |
rasmlar/manti.webp (o'sha nom) |
`/rasmlar/manti.webp` |
- Katta import — alohida fayl, nomida hash (
Czri_yu8). Rasm o'zgarsa — hash o'zgaradi, brauzer keshi eskisini bermaydi. Shuning uchun bunday fayllarni bir yilga keshlash xavfsiz (Code splitting va hash). - Kichik import (4 KB dan kichik,
build.assetsInlineLimit= 4096) — fayl yaratilmaydi, rasmdata:URL bo'lib JS ichiga yozildi. Bitta so'rov kam, lekin JS biroz kattalashdi. public/— nom va yo'l o'zgarmaydi, hash yo'q, Vite tekshirmaydi ham. Fayl yo'q bo'lsa, xato build'da emas, brauzerda (404) chiqadi.
Import qilingan faylning yana bir foydasi: fayl yo'q bo'lsa yoki nomi xato yozilsa, build yiqiladi. Xato foydalanuvchiga emas, sizga ko'rinadi.
2.3 TypeScript va rasm importi
import oshUrl from "./assets/osh.webp" TypeScript'da xatosiz — Vite'ning vite/client turlari .webp, .png, .svg va boshqalarni "satr eksport qiladigan modul" deb e'lon qiladi (tsconfig Vite + React darsidagi "types": ["vite/client"]). CSS Modules dagidek, bu tur faylning borligini tekshirmaydi — buni Vite build'da qiladi.
3. Ma'lumotdan rasm
3.1 Muammo: manzil satrda
Menyu ro'yxati ma'lumot: { name: "Osh", image: "osh" }. Rasm nomi ma'lumotda, import esa fayl boshida statik yoziladi. Uch yo'l:
1) Import + xarita obyekti — rasmlar oz bo'lsa eng aniq:
import osh from "./assets/osh.webp";
import lagmon from "./assets/lagmon.webp";
const IMAGES = { osh, lagmon }; // nom → manzil
// …
<img src={IMAGES[dish.image]} alt={dish.name} />2) new URL(…, import.meta.url) — Vite shablonli satrni tahlil qiladi va papkadagi hamma mos fayllarni build'ga qo'shadi:
function imageUrl(name: string): string {
return new URL(`./assets/${name}.webp`, import.meta.url).href;
}Build'dan keyin JS ichida (tekshirildi, Vite 8.3.4) Vite shunday xarita yasaydi:
new URL(Object.assign({"./assets/lagmon.webp":d,"./assets/osh.webp":f})[`./assets/${e}.webp`],import.meta.url).hrefassets/ dagi har .webp — hatto ishlatilmasa ham — bundle'ga kiradi. Papkada ortiqcha rasm saqlamang.
3) public/ + satr — rasmlar ko'p va tez-tez almashsa (masalan, CMS yoki server beradi): src={/rasmlar/${dish.image}.webp}. Hash yo'q, lekin kodni qayta build qilmasdan rasmni almashtirish mumkin. Serverdan keladigan rasmlar odatda to'liq URL bilan keladi — bu ham shu toifa.
3.2 public/ va base
public/ dagi fayl manzili sayt ildizidan: /rasmlar/manti.webp. Sayt pastki papkada ochilsa (GitHub Pages: foydalanuvchi.github.io/bahor-menyu/), bu manzil buziladi — /rasmlar/ sayt ildizida emas. Ikki yechim:
vite.config.tsdabaseni sozlash va manzilniimport.meta.env.BASE_URLdan yasash:src={`${import.meta.env.BASE_URL}rasmlar/manti.webp`}(Vite III: env);base: "./"va nisbiy manzil —vazifalaraynan shunday:vite.config.tsdabase: "./",index.htmldahref="assets/ikonlar/ikon.svg"(boshida/yo'q).
Import qilingan rasmlarda bu muammo yo'q — Vite base ni o'zi qo'shadi.
Shu darsda uchragan uchta Vite sozlamasi bir joyda:
Kalit (vite.config.ts) |
Nima qiladi | Sukut bo'yicha |
|---|---|---|
base |
sayt qaysi yo'lda ochiladi; import qilingan manzillar boshiga qo'shiladi | "/" |
build.assetsInlineLimit |
shundan kichik import qilingan fayl data: URL bo'lib JS ichiga yoziladi |
4096 (bayt) |
publicDir |
o'zgarishsiz nusxalanadigan papka | "public" |
Tekshirib ko'ring:
src/assets/logo.png(2 KB) import qilindi. Build'dan keyindist/assets/dalogo-….pngfayli bo'ladimi?
Javob
Yo'q. 2 KB — assetsInlineLimit (4 096 bayt) dan kichik, rasm data:image/png;base64,… bo'lib JS ichiga yoziladi. Alohida fayl kerak bo'lsa, chegarani o'zgartirasiz yoki rasmni public/ ga qo'yasiz.
4. SVG — komponent sifatida
4.1 <img> yoki JSX ichida
qalampir.svg ni <img src> bilan ulash mumkin, lekin SVG va ikonka pipeline darsidagi cheklov bor: rangni CSS'dan o'zgartirib bo'lmaydi, currentColor ishlamaydi. Ikonkani matn rangiga moslash uchun SVG sahifaning ichida bo'lishi kerak. React'da buning eng tabiiy yo'li — SVG'ni JSX qilib, komponent yasash:
function PepperIcon({ size = 24, title }) {
return (
<svg
viewBox="0 0 24 24"
width={size}
height={size}
role={title ? "img" : undefined}
aria-hidden={title ? undefined : true}
>
{title && <title>{title}</title>}
<path
d="M12 3c-3 4-6 7-6 11a6 6 0 0 0 12 0c0-4-3-7-6-11z"
fill="currentColor"
/>
</svg>
);
}
function App() {
return (
<ul>
<li style={{ color: "crimson" }}>
Lag'mon <PepperIcon size={16} title="Achchiq" />
</li>
<li>
<PepperIcon size={16} /> Achchiq taomlar
</li>
</ul>
);
}Ekranda:
Lag'mon Achchiq
Achchiq taomlarBitta ikonka, uch afzallik:
- o'lcham — props (
size), har joyda boshqacha; - rang —
fill="currentColor":<li>ningcolori (crimson) ikonka rangiga aylanadi; - ma'no — ikki holat. Ikonka yolg'iz ma'no tashisa (birinchi qator: "achchiq" so'zi yo'q),
role="img"va<title>— Malikaning ekran o'quvchisi "Achchiq, rasm" deb o'qiydi. Yonida matn bo'lsa (ikkinchi qator), ikonka bezak:aria-hiddenbilan ekran o'quvchidan yashiriladi, aks holda "Achchiq" ikki marta eshitiladi.
<title> matni ekran natijasida ham ko'rindi ("Lag'mon Achchiq") — u SVG ichidagi matn tuguni. Brauzer uni chizmaydi, faqat sichqoncha ustida turganda maslahat qilib ko'rsatadi.
4.2 SVG atributlari — camelCase
Dizayn dasturidan ko'chirilgan SVG ichida stroke-width, fill-rule, stroke-linecap kabi chiziqchali atributlar bo'ladi. JSX ularni JSX I dagi qoida bo'yicha camelCase'da kutadi:
function App() {
return (
<svg viewBox="0 0 24 24" width="24" height="24">
<path d="M4 12h16" stroke="black" stroke-width="2" />
</svg>
);
}Konsolda:
Invalid DOM property `stroke-width`. Did you mean `strokeWidth`?"Noto'g'ri DOM xususiyati stroke-width. strokeWidth ni nazarda tutdingizmi?" Ogohlantirish, xato emas — lekin chiziq qalinligi qo'llanmaydi. Tuzatish: strokeWidth="2". Istisnolar: viewBox va xmlns o'zgarishsiz qoladi; class → className; eski xlink:href → href. Oxirgisini JSX tahlilchisi umuman o'qimaydi (sintaksis xatosi) — SVG 2 da oddiy href yetadi.
Ko'p atributli katta SVG'ni qo'lda o'girish zerikarli. Buni avtomatik qiladigan vositalar bor: SVGR (keyingi bo'lim) va onlayn "SVG to JSX" o'giruvchilar.
4.3 vite-plugin-svgr — ?react import
SVG va ikonka pipeline darsida vite-plugin-svgr (5.2.0) ni tanishtirgan edik: "React — 17-qismda". Endi uning React tomonini ko'ramiz. Plagin ulangach, ?react qo'shimchali import SVG faylni komponentga aylantiradi:
import PepperIcon from "./assets/qalampir.svg?react";
export function SpicyBadge() {
return (
<span className="badge">
<PepperIcon width={16} height={16} aria-hidden="true" /> Achchiq
</span>
);
}SVGR faylni o'qib, xuddi «<img> yoki JSX ichida» bo'limida qo'lda yozgan komponentimizni o'zi yasaydi: atributlarni camelCase qiladi, props'ni <svg> ga uzatadi. Qaysi birini tanlash:
| Usul | Qachon |
|---|---|
<img src={url}> |
katta illyustratsiya, rangi o'zgarmaydi |
| qo'lda JSX komponent | bir nechta ikonka, to'liq nazorat |
?react (svgr) |
ko'p ikonka fayl ko'rinishida (dizayner beradi) |
sprite <use href="…#osh"> |
yuzlab bir xil o'lchamli ikonka |
| ikonka kutubxonasi (lucide-react) | tayyor to'plam yetsa — Ikonkalar |
5. <img> — to'g'ri atributlar
5.1 alt
Yaxshi alt matn yozish darsidagi qoidalar React'da ham o'sha, lekin bitta farq bor: React alt siz <img> uchun ogohlantirmaydi. Uni linter ushlaydi (eslint-plugin-jsx-a11y dagi alt-text qoidasi, ESLint II). Qoidani eslang:
- ma'no tashiydigan rasm — nima ko'rsatilganini ayting:
alt="Osh: guruch, sabzi va go'sht"; - bezak (yonida matn bor) —
alt=""(bo'sh, lekin bor!): ekran o'quvchi uni o'tkazib yuboradi; altumuman yo'q — eng yomoni: ko'p ekran o'quvchi fayl nomini o'qiydi ("osh tire C z r i…").
Ma'lumotdan chizilganda alt ham ma'lumotdan: alt={dish.name} — lekin taom nomi rasmning yaxshi tavsifi bo'lmasligi mumkin. Menyuda rasm ostida taom nomi allaqachon yozilgan bo'lsa — rasm bezak, alt="".
5.2 width, height va sakrash
Rasm yuklanguncha brauzer uning o'lchamini bilmaydi va unga joy ajratmaydi. Rasm kelganda matn pastga suriladi — foydalanuvchi bosmoqchi bo'lgan tugma qochib ketadi. Bu CLS (Cumulative Layout Shift), Performance API va Core Web Vitals darsidagi ko'rsatkich. width va height atributlari brauzerga nisbatni oldindan aytadi, CSS'dagi width: 100%; height: auto; bilan ham joy to'g'ri ajratiladi (Rasm unumdorligi).
import { flushSync } from "react-dom";
import { createRoot } from "react-dom/client";
const root = createRoot(document.getElementById("root"));
flushSync(() =>
root.render(
<img
src="/rasmlar/osh-480.webp"
srcSet="/rasmlar/osh-480.webp 480w, /rasmlar/osh-960.webp 960w"
sizes="(max-width: 600px) 100vw, 480px"
alt="Osh"
width={480}
height={320}
loading="lazy"
decoding="async"
/>,
),
);
console.log(document.getElementById("root").innerHTML);Konsolda:
<img sizes="(max-width: 600px) 100vw, 480px" alt="Osh" width="480" height="320" loading="lazy" decoding="async" srcset="/rasmlar/osh-480.webp 480w, /rasmlar/osh-960.webp 960w" src="/rasmlar/osh-480.webp">JSX'dagi nomlar HTML'dan farq qiladi: srcSet → srcset, fetchPriority → fetchpriority (camelCase, JSX I qoidasi). width={480} — son, React uni atributga "480" qilib yozadi. Atributlar tartibiga qarang: React sizes ni boshiga, srcset va src ni esa oxiriga qo'ydi. src yozilishi bilan brauzer yuklashni boshlaydi — undan oldin sizes va srcset tayyor bo'lsa, keraksiz o'lchamdagi rasm yuklanmaydi.
5.3 loading="lazy" va fetchPriority
loading="lazy"— ekrandan pastdagi rasm foydalanuvchi unga yaqinlashgandagina yuklanadi. Uzun menyu ro'yxatida trafikni tejaydi (Aziz sekin internetda).- Birinchi ekrandagi asosiy rasm (sahifa tepasidagi katta surat) — aksincha:
loading="lazy"qo'ymang,fetchPriority="high"qo'ying. U — LCP (eng katta element), kech yuklansa sahifa sekin tuyuladi.
HTML odati bilan kichik harfda yozsangiz:
function App() {
return <img src="/osh.webp" alt="Osh" fetchpriority="high" />;
}Konsolda:
Invalid DOM property `fetchpriority`. Did you mean `fetchPriority`?React 19 fetchPriority ni biladi va to'g'ri atributga aylantiradi.
flowchart TD
R["Rasm kerak"] --> Q{"Ikonka, rangi o'zgaradimi?"}
Q -- "ha" --> S["JSX SVG komponent yoki svgr"]
Q -- "yo'q" --> P{"Kod bilan birga o'zgaradimi?"}
P -- "ha" --> I["import: hash, build tekshiradi"]
P -- "yo'q, ko'p yoki tashqaridan" --> U["public/ yoki to'liq URL"]6. Vazifalar: ikonkalar public/ da
vazifalar da interfeys rasmlari yo'q, lekin ikonkalar bor: public/assets/ikonlar/ — ikon.svg, ikon-180.png, ikon-192.png, ikon-512.png, ikon-maskable-512.png. Ular 13-qismda PWA uchun yasalgan va manifest.webmanifest hamda index.html dan nomi bilan chaqiriladi. Nega public/, import emas?
manifest.webmanifest— JSON, Vite uning ichidagi manzillarni import deb o'qimaydi. Nom o'zgarmasligi kerak.- Service Worker (
sw.js) keshlaydigan fayllar ro'yxati (QOBIQ) nomlarni biladi — hash'li nom har build'da o'zgarardi. vercel.jsonda hamassets/ikonlar/hash'siz deb hisoblanadi: unga bir yillikimmutablekesh berilmaydi (/assets/((?!js/|ikonlar/).*)qoidasi). Buni mini-ilova darsida ko'ramiz.
Ya'ni public/ — "nomi o'zgarmasligi kerak bo'lgan fayllar" uchun. React'ga o'tish bu qarorni o'zgartirmadi. Bu darsda vazifalar kodiga o'zgarish yo'q.
7. Ko'p uchraydigan xatolar
| Belgi | Sabab | Davosi |
|---|---|---|
| dev'da bor, build'da singan rasm | src="./src/…" — satr, import emas |
import url from "…" yoki public/ |
GitHub Pages'da public/ rasmi 404 |
/rasmlar/… sayt ildizidan |
base + BASE_URL yoki nisbiy yo'l |
Invalid DOM property 'stroke-width' |
SVG HTML'dan ko'chirilgan | strokeWidth, fillRule |
| ikonka rangi o'zgarmaydi | <img src="ikon.svg"> |
JSX SVG + currentColor |
| sahifa yuklanishda sakraydi | width/height yo'q |
ikkalasini ham yozing |
| tepadagi katta rasm kech chiqadi | unga loading="lazy" qo'yilgan |
olib tashlang, fetchPriority="high" |
| ekran o'quvchi fayl nomini o'qiydi | alt yo'q |
alt="…" yoki bezak uchun alt="" |
8. Mashqlar
Mashqlar kurs/mashqlar/17/22-rasmlar/ da.
1-mashq (oson): Qayerga qo'yish kerak?
- PWA manifestidagi ikonka (
manifest.webmanifestdan nomi bilan chaqiriladi): - Taom kartasidagi 30 KB surat, kod bilan birga yangilanadi:
- 300 baytli kichik SVG
importqilinsa, build'da u qayerda bo'ladi — alohida faylda yoki JS ichida:
Yechim
Manifest ikonkasi — public/ (nomi o'zgarmasin). 30 KB surat — import (hash, build tekshiruvi). 300 bayt — assetsInlineLimit dan kichik, data: URL bo'lib JS ichiga yoziladi.
2-mashq (o'rta): Ikonka komponenti
«Bahor» uchun StarIcon komponentini yozing: props — filled (boolean), size (sukut bo'yicha 20), label (ixtiyoriy). filled bo'lsa fill="currentColor", aks holda fill="none" va stroke="currentColor", strokeWidth={2}. label berilsa — role="img" va <title>, berilmasa — aria-hidden. App uchta yulduz chizsin: ikkitasi to'la, biri bo'sh, oxirgisiga label="3 dan 2". Yulduz yo'li: M12 2l3 7h7l-5.5 4 2 7-6.5-4.5L5.5 20l2-7L2 9h7z.
Yechim
import { flushSync } from "react-dom";
import { createRoot } from "react-dom/client";
const STAR = "M12 2l3 7h7l-5.5 4 2 7-6.5-4.5L5.5 20l2-7L2 9h7z";
function StarIcon({ filled, size = 20, label }) {
return (
<svg
viewBox="0 0 24 24"
width={size}
height={size}
role={label ? "img" : undefined}
aria-hidden={label ? undefined : true}
>
{label && <title>{label}</title>}
<path
d={STAR}
fill={filled ? "currentColor" : "none"}
stroke={filled ? undefined : "currentColor"}
strokeWidth={filled ? undefined : 2}
/>
</svg>
);
}
const root = createRoot(document.getElementById("root"));
flushSync(() =>
root.render(
<p>
<StarIcon filled />
<StarIcon filled />
<StarIcon filled={false} label="3 dan 2" />
</p>,
),
);
const svgs = document.querySelectorAll("svg");
const path = svgs[2].querySelector("path");
console.log(svgs[0].getAttribute("aria-hidden"));
console.log(svgs[2].getAttribute("role"), svgs[2].textContent);
console.log(path.getAttribute("stroke-width"));Konsolda:
true
img 3 dan 2
2strokeWidth={2} DOM'da stroke-width="2" bo'ldi. undefined qiymatli atributlar (stroke, role) DOM'ga umuman yozilmaydi — "bo'lmasin" degani.
3-mashq (qiyin): Rasmli menyu — Vite loyihada
bahor-menyu ga src/assets/ papkasini qo'shing va unga ikkita rasm qo'ying (osh.webp, lagmon.webp — o'zingiz olgan surat yoki istalgan rasm). Menyu ma'lumoti: [{ id, name, image: "osh" }, …]. MenuCard rasmni new URL(…, import.meta.url) bilan topsin. Har rasmga width/height, birinchisidan boshqalariga loading="lazy", alt="" (nom rasm ostida yozilgan). npm run build qiling va dist/assets/ ni tekshiring: rasmlar hash bilanmi? Keyin assets/ ga uchinchi, ishlatilmaydigan rasm qo'shib, yana build qiling — u ham dist/ ga tushdimi?
Yechim
src/MenuCard.tsx:
type Dish = { id: number; name: string; image: string };
function imageUrl(name: string): string {
return new URL(`./assets/${name}.webp`, import.meta.url).href;
}
type Props = { dish: Dish; eager: boolean };
export function MenuCard({ dish, eager }: Props) {
return (
<li>
<img
src={imageUrl(dish.image)}
alt=""
width={160}
height={107}
loading={eager ? undefined : "lazy"}
/>
{dish.name}
</li>
);
}App da: MENU.map((d, i) => <MenuCard key={d.id} dish={d} eager={i === 0} />). Build'da rasmlar assets/osh-….webp kabi hash bilan chiqadi (4 KB dan katta bo'lsa). Uchinchi, ishlatilmagan rasm ham dist/ ga tushadi: Vite shablon ./assets/${name}.webp ga mos keladigan hamma faylni xaritaga qo'shadi — u qaysi nom ishlatilishini oldindan bilmaydi. Ikki rasm bir xil bo'lsa (bir faylni ikki nom bilan nusxalasangiz), dist/ da bitta fayl bo'ladi — hash tarkibdan hisoblanadi.
9. Real ishda
- E-commerce va menyu saytlarida rasm — sahifa og'irligining katta qismi.
width/height,loading="lazy",srcSet— Lighthouse tekshiruvida birinchi chiqadigan maslahatlar. - Ikonkalar — deyarli hamma React loyihada komponent:
lucide-react,react-iconsyoki svgr bilan o'zingizniki. Dizayner Figma'dan SVG beradi, siz uni komponentga aylantirasiz. - Framework'larda rasm uchun maxsus komponent bor (Next.js
<Image>— o'lcham, format, lazy avtomatik; 23-qism). Uning ichida aynan shu darsdagi atributlar. - Intervyu savollari: "React'da rasmni import qilish va
public/dan olish farqi?", "SVG'ni React'da qanday ishlatasiz?", "CLS'ning oldini olish uchun rasmga nima qo'shasiz?", "alt=\"\"vaaltyo'qligi farqi?".
Xulosa
- Import qilingan rasm — satr (manzil); katta fayl hash bilan alohida, 4 KB dan kichigi
data:URL; fayl yo'q bo'lsa build yiqiladi. public/— o'zgarishsiz nusxa, manzil qo'lda;basebilan ehtiyot bo'ling.- Ma'lumotdan rasm: import xaritasi,
new URL(…, import.meta.url)(papkadagi hamma mos fayl bundle'ga) yokipublic/. - SVG ikonka — JSX komponent: props bilan o'lcham,
currentColorbilan rang,role="img"+<title>yokiaria-hidden; atributlar camelCase; ko'p fayl — svgr?react. - Har
<img>:alt(bezak —alt=""),width/height; pastdagilargaloading="lazy", tepadagi asosiygafetchPriority="high".
Keyingi dars: Kichik React loyihani tashkil qilish — papkalar, fayl nomlari, colocation va vazifalar dagi komponentlar src/komponentlar/ ga ko'chadi.
Manbalar
- Vite: "Static Asset Handling" (import,
public,new URL,assetsInlineLimit) — vite.dev/guide/assets - React:
<img>— react.dev/reference/react-dom/components/common (fetchPriority,srcSet) - vite-plugin-svgr — github.com/pd4d10/vite-plugin-svgr (5.2.0)
- web.dev: "Optimize Cumulative Layout Shift" — web.dev/articles/optimize-cls
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!