Core Web Vitals ба оновчлол
Core Web Vitals бол Google-ийн вэб хуудасны гүйцэтгэлийг хэмждэг стандарт үзүүлэлт юм. Эдгээр үзүүлэлт нь хайлтын байр суурьт шууд нөлөөлдөг — гүйцэтгэл муутай сайт Google-д доор харагдана. Next.js нь Core Web Vitals-г сайжруулахад зориулсан олон built-in хэрэгсэлтэй тул та тэдгээрийг зөв хэрэглэж сурах хэрэгтэй.
Core Web Vitals гэж юу вэ?
| Үзүүлэлт | Нэр | Зорилт | | -------- | ------------------------- | ------------ | | LCP | Largest Contentful Paint | < 2.5 секунд | | INP | Interaction to Next Paint | < 200ms | | CLS | Cumulative Layout Shift | < 0.1 |
LCP — Хуудасны хамгийн том элемент (ихэвчлэн banner зураг эсвэл h1) хэдий хурдан харагдах вэ.
INP — Хэрэглэгч товшиход хуудас хэр хурдан хариу үйлдэл үзүүлэх вэ.
CLS — Хуудасны элементүүд ачааллах явцад хэр хөдөлдөг вэ (текст гэнэт доошоо унах зэрэг).
next/image ашиглан зураг оновчлох
Зураг бол LCP-н хамгийн гол шалтгаан. next/image нь автоматаар зургийг оновчилдог:
// components/lesson/LessonHero.tsx
import Image from "next/image";
interface LessonHeroProps {
src: string;
alt: string;
}
export default function LessonHero({ src, alt }: LessonHeroProps) {
return (
<div className="relative w-full h-64">
<Image
src={src}
alt={alt}
fill
priority // LCP зураг бол priority нэм
sizes="(max-width: 768px) 100vw, 50vw"
className="object-cover rounded-xl"
/>
</div>
);
}
Зургийн хэмжээг урьдчилан тодорхойлж CLS-г бууруулна:
// Хэмжээ тодорхой байвал width/height заана
<Image
src="/course-banner.png"
alt="JavaScript курс"
width={800}
height={400}
loading="lazy" // LCP биш зурагт lazy ашиглана
/>
next/font ашиглан фонт оновчлох
Google Fonts шууд ашиглахад layout shift үүсдэг. next/font/google энийг засдаг:
// app/layout.tsx
import { GeistSans, GeistMono } from 'next/font/google';
const geistSans = GeistSans({
subsets: ['latin'],
variable: '--font-geist-sans',
display: 'swap', // фонт ачаалах үед fallback харуулна
});
const geistMono = GeistMono({
subsets: ['latin'],
variable: '--font-geist-mono',
display: 'swap',
});
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="mn" className={`${geistSans.variable} ${geistMono.variable}`}>
<body>{children}</body>
</html>
);
}
Suspense болон streaming ашиглах
Удаан өгөгдөл татах хэсгийг Suspense-д орооход хуудас хурдан ачаалагддаг:
// app/courses/page.tsx
import { Suspense } from "react";
import CourseList from "@/components/CourseList";
import LoadingSpinner from "@/components/ui/LoadingSpinner";
export default function CoursesPage() {
return (
<main>
<h1 className="text-2xl font-bold mb-6">Сургалтууд</h1>
<Suspense fallback={<LoadingSpinner />}>
<CourseList />
</Suspense>
</main>
);
}
// app/courses/[courseSlug]/page.tsx
import { Suspense } from "react";
export default async function CoursePage({
params,
}: {
params: Promise<{ courseSlug: string }>;
}) {
const { courseSlug } = await params;
return (
<div>
<Suspense fallback={<p className="text-[#94a3b8]">Ачааллаж байна...</p>}>
<LessonProgress courseSlug={courseSlug} />
</Suspense>
</div>
);
}
Bundle хэмжээ хянах
Initial JS bundle 200KB-аас бага байх ёстой. next build ажиллуулахад bundle хэмжээ харагдана:
npm run build
Том dependency-г dynamic import-оор lazy load хийнэ:
// components/lesson/LessonPanel.tsx
'use client';
import dynamic from 'next/dynamic';
// react-markdown нь том library — dynamic import хийнэ
const ReactMarkdown = dynamic(() => import('react-markdown'), {
loading: () => <p className="text-[#94a3b8]">Ачааллаж байна...</p>,
});
export default function LessonPanel({ content }: { content: string }) {
return <ReactMarkdown>{content}</ReactMarkdown>;
}
Metadata оновчлох
SEO болон LCP-д зориулж metadata тохируулна:
// app/courses/[courseSlug]/page.tsx
import { Metadata } from "next";
export async function generateMetadata({
params,
}: {
params: Promise<{ courseSlug: string }>;
}): Promise<Metadata> {
const { courseSlug } = await params;
const course = await getCourse(courseSlug);
return {
title: `${course?.title} | Ulaanbaatar.app`,
description: course?.description,
openGraph: {
title: course?.title,
description: course?.description,
},
};
}
Vercel Analytics болон Speed Insights нэмж хуудасны гүйцэтгэлийг бодит цагаар хянаж болно — хоёулаа үнэгүй.
Дараагийн хичээлд:
Next.js аппын аюулгүй байдлыг хангах аргуудыг сурна. XSS, CSRF, environment variable-н аюулгүй байдал, Supabase Row Level Security зэрэг чухал сэдвийг авч үзнэ.