Next.js / next/image оновчлол

next/image оновчлол

Вэб сайтын удаашралын хамгийн том шалтгаануудын нэг бол оновчлогдоогүй зураг юм. HTML-н ердийн <img> tag ашиглавал зургийг шахахгүй, зөв хэмжээнд авчрахгүй, lazy load хийхгүй. Next.js-н next/image component эдгээр бүгдийг автоматаар хийдэг.

next/image яагаад хэрэгтэй вэ?

Ердийн <img> болон <Image> component-г харьцуулъя:

| Зүйл | <img> | <Image> | | ---------------- | ------- | ----------------- | | WebP хөрвүүлэлт | Үгүй | Тийм — автоматаар | | Lazy loading | Гараар | Анхнаасаа | | Хэмжээ оновчлол | Үгүй | Тийм | | Layout shift | Байдаг | Байхгүй | | Blur placeholder | Үгүй | Тийм |

Үндсэн хэрэглээ

next/image-г import хийж width болон height заавал зааж өгнө:

tsx
// components/CourseCard.tsx
import Image from "next/image";

interface Props {
  title: string;
  cover: string; // /images/javascript.png
}

export default function CourseCard({ title, cover }: Props) {
  return (
    <div>
      <Image src={cover} alt={title} width={400} height={225} loading="lazy" />
      <h2>{title}</h2>
    </div>
  );
}

width болон height нь зургийн харьцааг тооцоолоход хэрэглэгддэг — зураг ачаалахаас өмнө тэр хэмжээний зай хадгалагдах тул layout shift гардаггүй. Энэ нь Core Web Vitals-н CLS (Cumulative Layout Shift) оноог сайжруулдаг.

fill — контейнерийг бүрэн дүүргэх

Зургийн хэмжээ тодорхойгүй үед, эсвэл контейнерийг бүрэн дүүргэх шаардлагатай үед fill prop ашиглана:

tsx
// components/CourseBanner.tsx
import Image from "next/image";

export default function CourseBanner({ src }: { src: string }) {
  return (
    <div style={{ position: "relative", width: "100%", height: "200px" }}>
      <Image
        src={src}
        alt="Course banner"
        fill
        style={{ objectFit: "cover" }}
        sizes="100vw"
      />
    </div>
  );
}

fill ашиглахад эцэг элемент position: relative байх шаардлагатай. objectFit: 'cover' нь зургийг харьцаагаа хадгалан контейнерийг дүүргэнэ.

priority — LCP зургийг хурдасгах

Хуудасны дээд хэсэгт харагдах гол зурагт priority prop нэмнэ. Энэ нь тухайн зургийг lazy load хийхгүй, хамгийн түрүүнд татна — LCP (Largest Contentful Paint) оноог сайжруулдаг:

tsx
// app/page.tsx
import Image from "next/image";

export default function HomePage() {
  return (
    <main>
      {/* Хуудасны гол зурагт priority нэм */}
      <Image
        src="/images/hero.png"
        alt="Ulaanbaatar.app"
        width={1200}
        height={600}
        priority // ← lazy load хийхгүй, нэн даруй татна
      />
    </main>
  );
}

priority зөвхөн above-the-fold зурагт (дэлгэцийн анхны харагдах хэсэгт) ашиглана — бусад зурагт хэрэггүй.

Гадны зургийн domain зөвшөөрөх

Supabase storage эсвэл бусад гадны сервисийн зургийг ашиглах бол next.config.ts дотор domain зөвшөөрнө:

typescript
// next.config.ts
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: "https",
        hostname: "*.supabase.co",
        pathname: "/storage/v1/object/public/**",
      },
    ],
  },
};

export default nextConfig;

Зөвшөөрөгдөөгүй domain-н зургийг <Image> дуудвал Next.js алдаа гаргана — энэ нь аюулгүй байдлын хамгаалалт юм.

Дараагийн хичээлд:

next/font ашиглан Google Fonts болон локал фонтыг хэрхэн оновчлон ачаалах, layout shift-г арилгах аргыг сурна.