IlmHamroh
JavaScript Full-stack/17-qism. React asoslari22/45-dars15 daqiqa
Mundarija (26)

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 esa data: 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> ga alt (bezak bo'lsa — alt=""), width va height (sahifa sakramasin), pastdagi rasmlarga loading="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, fetchPriority ni 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

tsx
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):

bash
npx vite build

Chiqishda uch faylni qidiring: osh rasmi bormi, qalampir bormi, manti bormi?

text
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 136ms

Uch 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, rasm data: 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:

tsx
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:

tsx
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:

text
new URL(Object.assign({"./assets/lagmon.webp":d,"./assets/osh.webp":f})[`./assets/${e}.webp`],import.meta.url).href

assets/ 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.ts da base ni sozlash va manzilni import.meta.env.BASE_URL dan yasash: src={`${import.meta.env.BASE_URL}rasmlar/manti.webp`} (Vite III: env);
  • base: "./" va nisbiy manzil — vazifalar aynan shunday: vite.config.ts da base: "./", index.html da href="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 keyin dist/assets/ da logo-….png fayli 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:

jsx
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:

text
Lag'mon Achchiq
Achchiq taomlar

Bitta ikonka, uch afzallik:

  • o'lcham — props (size), har joyda boshqacha;
  • rang — fill="currentColor": <li> ning color i (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-hidden bilan 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:

jsx
function App() {
  return (
    <svg viewBox="0 0 24 24" width="24" height="24">
      <path d="M4 12h16" stroke="black" stroke-width="2" />
    </svg>
  );
}

Konsolda:

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

tsx
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;
  • alt umuman 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).

jsx
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:

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

jsx
function App() {
  return <img src="/osh.webp" alt="Osh" fetchpriority="high" />;
}

Konsolda:

text
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.json da ham assets/ikonlar/ hash'siz deb hisoblanadi: unga bir yillik immutable kesh 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.webmanifest dan nomi bilan chaqiriladi):
  • Taom kartasidagi 30 KB surat, kod bilan birga yangilanadi:
  • 300 baytli kichik SVG import qilinsa, 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
jsx
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:

text
true
img 3 dan 2
2

strokeWidth={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:

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-icons yoki 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=\"\" va alt yo'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; base bilan ehtiyot bo'ling.
  • Ma'lumotdan rasm: import xaritasi, new URL(…, import.meta.url) (papkadagi hamma mos fayl bundle'ga) yoki public/.
  • SVG ikonka — JSX komponent: props bilan o'lcham, currentColor bilan rang, role="img"+<title> yoki aria-hidden; atributlar camelCase; ko'p fayl — svgr ?react.
  • Har <img>: alt (bezak — alt=""), width/height; pastdagilarga loading="lazy", tepadagi asosiyga fetchPriority="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
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Rasm, SVG va assetlar React komponentlarida: import, public va alt — IlmHamroh