Mundarija (28)
- Bu darsda
- 1. Nega bu kerak?
- 2. metadata va generateMetadata
- 2.1 Ikki usul
- 2.2 Biz sinadik: ikkalasi birga
- 3. title shabloni
- 3.1 template va default
- 4. metadataBase va canonical
- 4.1 Nisbiy manzillar
- 4.2 Biz topdik: canonical meros bo'lib o'tadi
- 4.3 Biz topdik: SAYT_URL build vaqtida yoziladi
- 5. Open Graph va Twitter
- 5.1 Teglar
- 5.2 Biz topdik: sahifadagi openGraph almashtiradi
- 6. viewport — alohida eksport
- 7. Metadata va tezlik
- 8. Portfolio qadami: metadata
- 8.1 Fayllar (holat 30 ning bir qismi)
- 8.2 Tekshiruv
- 9. Ko'p uchraydigan xatolar
- 10. Mashqlar
- 1-mashq (oson): qayerga yoziladi?
- 2-mashq (o'rta): chuqur birlashtirish
- 3-mashq (qiyin): canonical tekshiruvchi
- 4-mashq: Portfolio qadami
- 11. Real ishda
- Xulosa
- Manbalar
Next.js Metadata API: title shabloni, canonical, Open Graph va viewport
Qisqacha: Next.js'da
<head>qo'lda yozilmaydi.layout.tsxyokipage.tsxdanexport const metadata = { … }(o'zgarmas) yokiexport async function generateMetadata()(ma'lumotga bog'liq) qaytarasiz — Next undan<title>,description, canonical, Open Graph va Twitter teglarini yasaydi. Ota layout va sahifa metadata'si yuzaki birlashadi: sahifadagiopenGraphlayout'dagiopenGraphni butunlay almashtiradi.themeColorkabi qiymatlar alohidaviewporteksportida.
Bu darsda
metadatavagenerateMetadatafarqini va ikkalasini birga yozib bo'lmasligini (haqiqiy xato) bilasiz.title.templatebilan har sahifaga " — Aziz Karimov" qo'shimchasini bir joydan berasiz.metadataBase,alternates.canonicalva canonical'ning meros tuzog'ini tushuntirasiz.- Open Graph va Twitter teglarini yozasiz va
openGraphalmashtirish tuzog'ini haqiqiy HTML bilan ko'rasiz. viewporteksporti bilan manzil satri rangini yorug'/qorong'i rejimga moslaysiz.
Oldin bilishingiz kerak: SPA uchun SEO, Layout va template, Rendering strategiyalari, Spread va rest operatori.
1. Nega bu kerak?
SPA uchun SEO darsida vazifalar ning <title> ini useEffect bilan o'zgartirgan edingiz va katta muammoni ko'rgansiz: Telegram, Facebook kabi havola ko'rinishini yasaydigan botlar JS'ni bajarmaydi. Ular faqat birinchi HTML'ni o'qiydi — SPA'da u bo'sh.
Next'da sahifa serverda tayyor bo'ladi. Endi faqat to'g'ri teglarni qo'yish qoldi. portfolio holat 27 da esa har sahifada shunday qator turibdi:
export const metadata: Metadata = { title: "Aloqa — Aziz Karimov" };Uchta kamchilik bor. " — Aziz Karimov" har faylda takrorlanadi. Tavsif (description) yo'q — Google o'zi biror gapni tanlab oladi. Ijtimoiy tarmoq uchun rasm va sarlavha (Open Graph) yo'q — Telegram'da havola quruq matn bo'lib chiqadi.
Hayotiy o'xshatish: kitob muqovasi. Kitob ichi (sahifa matni) qanchalik yaxshi bo'lmasin, do'kon peshtaxtasida xaridor avval muqovani ko'radi: nom, qisqa tavsif, rasm. Metadata — sahifaning muqovasi: Google natijasida, Telegram havolasida, brauzer tabida.
2. metadata va generateMetadata
2.1 Ikki usul
| Usul | Qachon | Misol |
|---|---|---|
export const metadata |
qiymat oldindan ma'lum | «Aloqa» sahifasi |
export async function generateMetadata() |
qiymat ma'lumotga bog'liq | loyiha nomi params.slug dan |
Ikkalasi ham faqat Server Component faylida (layout.tsx, page.tsx) ishlaydi. "use client" faylidan metadata eksport qilib bo'lmaydi.
Kanondagi loyiha sahifasi (holat 30, loyihalar/[slug]/page.tsx dan):
export async function generateMetadata({
params,
}: PageProps<"/loyihalar/[slug]">): Promise<Metadata> {
const loyiha = await loyihaniOl((await params).slug);
if (!loyiha) return {};
return {
title: loyiha.nomi,
description: loyiha.qisqa,
alternates: { canonical: `/loyihalar/${loyiha.slug}` },
};
}loyihaniOl — sahifa komponenti ham chaqiradigan DAL funksiyasi. Ikki marta chaqirilsa ham bazaga bir marta boradi: React cache() darsidagi so'rov ichidagi memoizatsiya. Loyiha topilmasa — {}: sahifa baribir notFound() qiladi.
2.2 Biz sinadik: ikkalasi birga
Bitta faylda ikkalasini yozsa nima bo'ladi? portfolio nusxasida sinadik (next dev, biz ishga tushirdik, next 16.4.0):
export const metadata: Metadata = { title: "Bir" };
export async function generateMetadata(): Promise<Metadata> {
return { title: "Ikki" };
}Error: "metadata" and "generateMetadata" cannot be exported at the same time, please keep one of them. Read more: https://nextjs.org/docs/app/api-reference/file-conventions/metadataTarjimasi: "metadata va generateMetadata bir vaqtda eksport qilinmaydi, bittasini qoldiring". Xato kompilyatsiya bosqichida — sahifa umuman ochilmaydi.
3. title shabloni
3.1 template va default
Root layout'da (holat 30):
export const metadata: Metadata = {
metadataBase: new URL(SAYT_URL),
title: {
default: "Aziz Karimov — frontend dasturchi",
template: "%s — Aziz Karimov",
},
description:
"Aziz Karimovning portfoliosi: loyihalar va case study, blog, aloqa.",
openGraph: { ...OG_ASOS, type: "website" },
twitter: { card: "summary_large_image" },
};Sahifalarda endi faqat qisqa nom: title: "Aloqa". Next uni shablonga qo'yadi: %s o'rniga sahifa nomi.
| Sahifa | title |
<title> |
|---|---|---|
/aloqa |
"Aloqa" |
Aloqa — Aziz Karimov |
/loyihalar/vazifalar |
loyiha.nomi |
Vazifalar ilovasi — Aziz Karimov |
/ |
yo'q | Aziz Karimov — frontend dasturchi |
Uchinchi qator — default: sahifa nom bermasa, shu. Hujjatdagi muhim qoida: shablon faqat bola segmentlarga qo'llanadi, o'zi turgan segmentga emas. Shuning uchun default majburiy, va shablonni page.tsx ga yozish befoyda (sahifaning bolasi yo'q). Shablonni chetlab o'tish kerak bo'lsa — title: { absolute: "…" }.
Shablon ishini oddiy JS'da takrorlaymiz:
function sarlavhaYasa(sahifaNomi, shablon) {
if (!sahifaNomi) return shablon.default;
return shablon.template.replace("%s", sahifaNomi);
}
const shablon = {
default: "Aziz Karimov — frontend dasturchi",
template: "%s — Aziz Karimov",
};
console.log(sarlavhaYasa("Aloqa", shablon));
console.log(sarlavhaYasa("Vazifalar ilovasi — skrinshot", shablon));
console.log(sarlavhaYasa(undefined, shablon));Konsolda:
Aloqa — Aziz Karimov
Vazifalar ilovasi — skrinshot — Aziz Karimov
Aziz Karimov — frontend dasturchiIkkinchi qator kanondagi rasm sahifasining haqiqiy sarlavhasi bilan bir xil (natijalar/30-seo.txt): "Vazifalar ilovasi — skrinshot — Aziz Karimov".
4. metadataBase va canonical
4.1 Nisbiy manzillar
Open Graph rasmi va canonical to'liq manzil bo'lishi kerak (https://…): Telegram boti /loyihalar/vazifalar.png dan qaysi saytni olishni bilmaydi. metadataBase — nisbiy manzillarga qo'shiladigan asos:
metadataBase: new URL(SAYT_URL), // https://example.com
// sahifada:
alternates: { canonical: "/aloqa" },
// HTML'da: <link rel="canonical" href="https://example.com/aloqa"/>Canonical (SPA uchun SEO darsidan) — "bu sahifaning asl manzili shu": ?utm=telegram kabi qo'shimchali nusxalar Google'da bitta sahifa bo'lib hisoblanadi.
4.2 Biz topdik: canonical meros bo'lib o'tadi
Birinchi urinishda kanon alternates: { canonical: "/" } ni root layout'ga yozgan edi — "bosh sahifa uchun". Natija: canonical bermagan har sahifa (rasm sahifasi, 404) uni meros oldi va o'zini bosh sahifaning nusxasi deb e'lon qildi. Google bunday sahifalarni indeksdan chiqarib, bosh sahifaga "birlashtiradi".
Tuzatish — canonical faqat (sayt)/page.tsx da:
// canonical root layout'da EMAS: u hamma sahifaga meros o'tib,
// ularni "/" ning nusxasi deb e'lon qilardi
export const metadata: Metadata = { alternates: { canonical: "/" } };Tuzatilgandan keyingi o'lchov (natijalar/30-seo.txt, bir nechta qator, ogImage maydoni qisqartirilgan):
/: {"title":"Aziz Karimov — frontend dasturchi","canonical":"https://example.com","ogType":"website"}
/aloqa: {"title":"Aloqa — Aziz Karimov","canonical":"https://example.com/aloqa","ogType":"website"}
/loyihalar/vazifalar: {"title":"Vazifalar ilovasi — Aziz Karimov","canonical":"https://example.com/loyihalar/vazifalar","ogType":"article"}
/yoq: {"title":"Sahifa topilmadi — Aziz Karimov","canonical":"-","robots":"noindex"}Har sahifaning canonical'i o'ziniki, 404 da — yo'q (-) va noindex (404 statusda Next uni o'zi qo'shadi).
4.3 Biz topdik: SAYT_URL build vaqtida yoziladi
metadataBase uchun SAYT_URL holat 30 da kodda o'zgarmas ("https://example.com"). Keyinroq (Env o'zgaruvchilar) u .env ga ko'chadi. Kanon u yerda tajriba qildi: build'ni bitta qiymat bilan, next start ni boshqasi bilan ishga tushirdi (natijalar/tajriba/37-env-instrumentation.txt):
## B) env: build SAYT_URL=https://build.example.uz, start SAYT_URL=https://run.example.uz
<link rel="canonical" href="https://build.example.uz"/>
<loc>https://build.example.uz/</loc>
<link>https://build.example.uz/blog</link>Hammasi build qiymati bilan. Sababi: sahifalar statik (○) — metadata HTML bilan birga build'da tayyor bo'lgan. Server keyin qiymatni o'zgartirsa ham, tayyor HTML o'zgarmaydi. Saboq: domen o'zgarsa — qayta build. Lighthouse SEO ham shu bilan bog'liq: kanon lokal o'lchovda canonical example.com bo'lgani uchun SEO 92 oldi; SAYT_URL=http://localhost:3127 bilan build qilinganda — 100 (38-lighthouse-sayt-url-lokal.txt).
Tekshirib ko'ring: Nega Next
metadataBasesiz nisbiyog:imageni o'zi to'ldirib qo'ya olmaydi — axir so'rovningHostsarlavhasi bor-ku?
Javob
Statik sahifa build'da yasaladi — o'shanda so'rov ham, Host ham yo'q. Bundan tashqari Host ga ishonib bo'lmaydi: uni so'rovchi yozadi (Request API'lar darsidagi sarlavhalar qoidasi). Shuning uchun asos manzil sozlamadan keladi.
5. Open Graph va Twitter
5.1 Teglar
Open Graph — Facebook boshlagan, hozir Telegram, WhatsApp, LinkedIn o'qiydigan <meta property="og:…"> teglari: havola ko'rinishidagi sarlavha, tavsif, rasm. Twitter (X) o'z twitter:card tegini ham o'qiydi; summary_large_image — katta rasmli karta.
/aloqa sahifasining haqiqiy <head> qismi (holat 32 nusxasi, next dev, biz ishga tushirdik; dev'da rasm manzili localhost bilan chiqadi, build'da — metadataBase):
<title>Aloqa — Aziz Karimov</title>
<meta property="og:title" content="Aloqa — Aziz Karimov"/>
<meta property="og:description" content="Aziz Karimov bilan bog'lanish: email, Telegram va aloqa formasi."/>
<meta property="og:site_name" content="Aziz Karimov"/>
<meta property="og:locale" content="uz_UZ"/>
<meta property="og:image" content="http://localhost:47914/opengraph-image?405533f4f4463540"/>
<meta property="og:type" content="website"/>
<meta name="twitter:card" content="summary_large_image"/>Sahifada faqat title va description yozilgan — og:title va og:description ni Next ulardan o'zi to'ldirdi. og:site_name va og:locale — root layout'dan, rasm — opengraph-image.tsx faylidan (keyingi darsda).
5.2 Biz topdik: sahifadagi openGraph almashtiradi
Loyiha sahifasiga o'z openGraph ini berdik: type: "article" (maqola) va loyiha rasmi. Kutilgani: layout'dagi siteName va locale saqlanadi, faqat type va rasm qo'shiladi. Aslida — kanonning birinchi urinishida /loyihalar/vazifalar da og:type va og:site_name yo'qolgan edi.
Next metadata'ni root'dan sahifagacha tartib bilan yig'adi. Har segment oldingisining ustiga yoziladi — lekin faqat yuqori darajadagi kalitlar bo'yicha:
flowchart LR
L["root layout<br/>title, description,<br/>openGraph: siteName, locale"] --> P["sahifa<br/>title,<br/>openGraph: type"]
P --> N["natija<br/>title — sahifadan<br/>description — layout'dan<br/>openGraph — FAQAT sahifadan"]description sahifada yo'q — layout'niki qoladi. openGraph esa sahifada bor — u bitta butun qiymat sifatida layout'nikini almashtiradi, ichidagi maydonlar aralashmaydi.
Buni toza sinab ko'rdik: sahifa faqat openGraph: { type: "article" } beradi (biz ishga tushirdik):
<title>Sinov — Aziz Karimov</title>
<meta property="og:title" content="Sinov — Aziz Karimov"/>
<meta property="og:description" content="Aziz Karimovning portfoliosi: loyihalar va case study, blog, aloqa."/>
<meta property="og:type" content="article"/>
<meta name="twitter:card" content="summary_large_image"/>og:site_name, og:locale va hatto og:image ham yo'q — yuqoridagi /aloqa bilan solishtiring. Hujjat buni aniq yozadi: metadata obyektlari yuzaki (shallow) birlashadi — openGraph kabi ichma-ich maydonni oxirgi segment butunlay almashtiradi.
"Yuzaki birlashish" — spread aynan shunday ishlaydi:
const layout = {
title: "Aziz Karimov",
openGraph: {
siteName: "Aziz Karimov",
locale: "uz_UZ",
type: "website",
},
};
const sahifa = { title: "Vazifalar", openGraph: { type: "article" } };
const natija = { ...layout, ...sahifa };
console.log(natija.openGraph);
const OG_ASOS = { siteName: "Aziz Karimov", locale: "uz_UZ" };
const tuzatilgan = { openGraph: { ...OG_ASOS, type: "article" } };
console.log({ ...layout, ...tuzatilgan }.openGraph);Konsolda:
{ type: 'article' }
{ siteName: 'Aziz Karimov', locale: 'uz_UZ', type: 'article' }Birinchi natijada siteName va locale yo'qoldi: openGraph kaliti bitta qiymat sifatida almashdi, ichi birlashmadi. Kanon yechimi — umumiy maydonlar bitta o'zgarmasda (src/malumot/sozlama.ts) va har openGraph da yoyiladi:
// Open Graph umumiy maydonlari. Sahifadagi `openGraph` ota
// layout'nikini BUTUNLAY almashtiradi (birlashtirmaydi) —
// shuning uchun har joyda shu obyekt yoyiladi (holat 30 topilmasi).
export const OG_ASOS = { siteName: "Aziz Karimov", locale: "uz_UZ" } as const;Loyiha sahifasi endi:
openGraph: {
...OG_ASOS,
type: "article",
images: [
{
url: loyiha.rasm.fayl,
width: loyiha.rasm.eni,
height: loyiha.rasm.boyi,
alt: loyiha.rasm.alt,
},
],
},Rasm ham aniq berildi — chunki layout'dan meros endi kelmaydi. Tuzatishdan keyin /loyihalar/vazifalar da og:type — article, og:image — loyiha skrinshoti.
Tekshirib ko'ring:
robotsham ichma-ich obyekt ({ index, follow }). Layoutrobots: { index: true, follow: true }, sahifarobots: { index: false }bersa, sahifadagifollowqanday bo'ladi?
Javob
follow umuman yozilmaydi — sahifaning robots i layout'nikini butunlay almashtirdi, follow: true meros bo'lmadi. Hujjat robots ni ham openGraph bilan birga misol qilib keltiradi. Kerak bo'lsa, sahifada ikkalasini aniq yozing.
6. viewport — alohida eksport
themeColor (telefonda manzil satrining rangi), colorScheme, width kabi qiymatlar Next 14 dan beri metadata da emas (u yerda eskirgan — deprecated), alohida viewport eksportida:
import type { Metadata, Viewport } from "next";
// viewport alohida eksport (N-29): manzil satri rangi
// yorug'/qorong'i rejimda
export const viewport: Viewport = {
themeColor: [
{ media: "(prefers-color-scheme: light)", color: "#f7faf8" },
{ media: "(prefers-color-scheme: dark)", color: "#16231d" },
],
};HTML'da ikkita <meta name="theme-color" media="…"> chiqadi: telefon o'zi tizim mavzusiga qarab tanlaydi. Ranglar — v1 dagi fon tokenlari. Qiymat ma'lumotga bog'liq bo'lsa — generateViewport(). <meta charset> va <meta name="viewport" content="width=device-width, initial-scale=1"> ni Next sukut bo'yicha o'zi qo'shadi.
7. Metadata va tezlik
generateMetadata ichida sekin so'rov bo'lsa, sahifa uni kutadimi? Next 15.2 dan beri — metadata oqimi (streaming metadata): oddiy brauzer va JS bajaradigan botlar (Googlebot) uchun sahifa kutilmaydi, teglar tayyor bo'lgach <body> ga qo'shiladi. JS bajarmaydigan botlar (facebookexternalhit kabi — Next ularni User-Agent dan taniydi) uchun esa teglar <head> da va sahifa ularni kutadi.
Cache Components yoqilgan loyihada qoida yana bitta: metadata cookies()/headers() yoki keshlanmagan so'rov ishlatsa, u so'rov vaqtiga suriladi. Sahifaning qolgani statik bo'lsa, Next xato bilan aniq tanlov so'raydi — "use cache" yoki ataylab dinamik belgisi. portfolio da bu muammo yo'q: metadata ma'lumoti (loyihalar, postlar) allaqachon keshlangan DAL'dan keladi, sahifalar ○ qoladi.
8. Portfolio qadami: metadata
8.1 Fayllar (holat 30 ning bir qismi)
| Fayl | O'zgarish |
|---|---|
app/layout.tsx |
metadataBase, title shabloni, description, openGraph, twitter; viewport eksporti |
malumot/sozlama.ts |
OG_ASOS |
(sayt)/page.tsx |
faqat alternates.canonical: "/" |
aloqa, haqimda, loyihalar, blog sahifalari |
qisqa title, description, canonical |
blog/page.tsx |
alternates.types — RSS havolasi |
loyihalar/[slug], blog/[slug], [slug]/rasm |
generateMetadata: canonical, openGraph (...OG_ASOS, article) |
not-found.tsx |
title: "Sahifa topilmadi" (shablon qo'shimchasini o'zi oladi) |
Blog ro'yxatidagi RSS havolasi:
alternates: {
canonical: "/blog",
types: { "application/rss+xml": "/blog/rss.xml" },
},U <link rel="alternate" type="application/rss+xml"> bo'ladi: RSS o'quvchi dastur blog sahifasidan lentani o'zi topadi. Bu Route Handlers darsidagi /blog/rss.xml va'dasining bajarilishi.
8.2 Tekshiruv
npm run lint
npm run tip
npm run build
npm run startBrauzerda har sahifada Ctrl+U (sahifa manbasi) — <title>, canonical va og: teglarini tekshiring. Telegram'da havola ko'rinishini sinash uchun sayt internetda bo'lishi kerak — bu deploy darsida.
Hali commit qilmang: kanonda holat 30 keyingi dars (sitemap, robots, OG rasmlar) bilan bitta commit.
9. Ko'p uchraydigan xatolar
| Belgi | Sabab | Davosi |
|---|---|---|
"metadata" and "generateMetadata" cannot be exported at the same time |
Bir faylda ikkalasi | Bittasini qoldiring |
| Sarlavhada " — Aziz Karimov" ikki marta | Sahifa ham, shablon ham qo'shimcha yozadi | Sahifada faqat qisqa nom |
| Shablon bosh sahifada ishlamaydi | Shablon o'z segmentiga qo'llanmaydi | title.default |
| Hamma sahifa canonical'i — bosh sahifa | canonical: "/" root layout'da |
Faqat (sayt)/page.tsx da |
og:site_name, og:image yo'qoldi |
Sahifadagi openGraph almashtirdi |
...OG_ASOS va rasmni aniq bering |
og:image nisbiy, Telegram rasm ko'rsatmaydi |
metadataBase yo'q |
Root layout'da metadataBase |
themeColor ogohlantirish beradi |
metadata ichida |
export const viewport |
| Domen o'zgardi, canonical eskicha | Statik sahifa build'da yasalgan | Qayta build |
10. Mashqlar
Mashqlar kurs/mashqlar/23/29-metadata/ da. Jonli yechimlarni «Ishga tushir» bilan sinang.
1-mashq (oson): qayerga yoziladi?
metadataBase—- Loyiha nomidan sarlavha —
themeColor—- Bosh sahifaning
canonical: "/"—
Yechim
- root layout — hamma sahifaga umumiy asos manzil.
- generateMetadata — qiymat
paramsva ma'lumotga bog'liq. - viewport — Next 14 dan alohida eksport.
- page.tsx — bosh sahifaning o'zida; layout'da bo'lsa meros bo'lib hamma joyga o'tadi.
2-mashq (o'rta): chuqur birlashtirish
«yuzaki birlashish» blokidagi layout va sahifa ni oling va metaBirlashtir(ota, bola) funksiyasini yozing: oddiy maydonlar bola'nikidan, openGraph esa ikkala obyektni yoyib birlashsin. Next shunday qilmaydi — bu funksiya OG_ASOS naqshining avtomatik varianti. Natijani console.log qiling.
Yechim
function metaBirlashtir(ota, bola) {
return {
...ota,
...bola,
openGraph: { ...ota.openGraph, ...bola.openGraph },
};
}
const layout = {
title: "Aziz Karimov",
openGraph: {
siteName: "Aziz Karimov",
locale: "uz_UZ",
type: "website",
},
};
const sahifa = { title: "Vazifalar", openGraph: { type: "article" } };
console.log(metaBirlashtir(layout, sahifa));Konsolda:
{
title: 'Vazifalar',
openGraph: { siteName: 'Aziz Karimov', locale: 'uz_UZ', type: 'article' }
}openGraph ichida ota maydonlari saqlandi, type — bola'niki. Next'ning o'zi bunday qilmaydi (hujjat — yuzaki birlashish), shuning uchun haqiqiy loyihada generateMetadata ichida { ...OG_ASOS, type: "article" } yozasiz. Bunday yordamchi funksiyani o'zingiz ham yozishingiz mumkin — lekin u har sahifada chaqirilishi kerak.
3-mashq (qiyin): canonical tekshiruvchi
natijalar/30-seo.txt kabi o'lchov natijasini tekshiradigan funksiya yozing: har sahifa { yol, canonical, robots }. Qoidalar: noindex sahifada canonical bo'lmasin; qolganlarida canonical SAYT + yol ga teng bo'lsin (/ uchun — SAYT ning o'zi). Xato topilsa — XATO: yo'l — sabab, bo'lmasa OK: yo'l. Massiv bo'ylab yurish — for...of.
Yechim
const SAYT = "https://example.com";
const sahifalar = [
{ yol: "/", canonical: "https://example.com" },
{ yol: "/aloqa", canonical: "https://example.com/aloqa" },
{
yol: "/loyihalar/vazifalar/rasm",
canonical: "https://example.com",
},
{ yol: "/yoq", canonical: "-", robots: "noindex" },
];
for (const s of sahifalar) {
const kutilgan = s.yol === "/" ? SAYT : SAYT + s.yol;
if (s.robots === "noindex") {
const ok = s.canonical === "-";
console.log(ok ? `OK: ${s.yol}` : `XATO: ${s.yol}`);
} else if (s.canonical !== kutilgan) {
console.log(`XATO: ${s.yol} — canonical ${s.canonical}`);
} else {
console.log(`OK: ${s.yol}`);
}
}Konsolda:
OK: /
OK: /aloqa
XATO: /loyihalar/vazifalar/rasm — canonical https://example.com
OK: /yoqUchinchi qator — aynan kanonning birinchi urinishidagi meros tuzog'i: rasm sahifasi o'zini bosh sahifa deb e'lon qilgan. Bunday tekshiruvni e2e testga qo'shsangiz (Playwright), tuzoq qaytib kelmaydi.
4-mashq: Portfolio qadami
O'z portfolio ingizga «Portfolio qadami» bo'limidagi metadata'ni qo'shing: shablon, metadataBase, har sahifaga description va canonical, loyiha va post sahifalariga generateMetadata (...OG_ASOS bilan), viewport. next build && next start dan keyin 3 ta sahifaning manbasida <title>, canonical, og:type va og:site_name ni tekshiring.
Yechim
Kutilgan: /aloqa — «Aloqa — Aziz Karimov», canonical …/aloqa, og:type website, og:site_name Aziz Karimov; /loyihalar/vazifalar — og:type article va og:site_name saqlangan; / — default sarlavha. og:site_name yo'q bo'lsa — OG_ASOS yoyilmagan. SAYT_URL ni o'z domeningizga almashtirishni unutmang (GitHub Pages yoki keyingi deploy manzili). Commit — keyingi darsda.
11. Real ishda
- Har Next loyihasida root layout'da
metadataBasevatitle.template— birinchi qatorlardan. Ko'p jamoalarOG_ASOSkabi umumiy obyekt yokibuildMetadata()yordamchisini yozadi. - E-commerce: mahsulot sahifasi
generateMetadatada nom, narx tavsifi va rasmni bazadan oladi — Telegram'da ulashilgan havola mahsulot kartochkasiga aylanadi. - SEO auditlari (Lighthouse, Ahrefs, Semrush) birinchi navbatda canonical, title uzunligi va description'ni tekshiradi — kanondagi SEO 92 → 100 farqi aynan canonical'dan.
- Intervyu savoli: "metadata va generateMetadata farqi?", "Nega sahifadagi openGraph layout'dagini o'chirib yuboradi?" — yuzaki birlashishni bilish kamdan-kam uchraydigan, kuchli javob.
Xulosa
metadata— o'zgarmas,generateMetadata— ma'lumotga bog'liq; bir faylda faqat bittasi, faqat Server Component'da.title.templatesarlavha qo'shimchasini bir joydan beradi; o'z segmentiga qo'llanmaydi, shuning uchundefaultmajburiy.metadataBasenisbiy manzillarni to'liq qiladi; canonical root layout'da bo'lsa hamma sahifaga meros bo'ladi — faqat bosh sahifada.- Metadata yuzaki birlashadi: sahifadagi
openGraphlayout'nikini butunlay almashtiradi —...OG_ASOSnaqshi. viewportalohida eksport; statik sahifa metadata'si (vaSAYT_URL) build vaqtida yoziladi.
Keyingi dars: SEO fayllari va OG rasmlar — sitemap.ts, robots.ts, manifest.ts va kod bilan chiziladigan Open Graph rasmlarini qo'shamiz.
Manbalar
- Next.js hujjati (16.4.0,
node_modules/next/dist/docs/):generateMetadata— title template, metadataBase, Merging, Streaming metadata, With Cache Components;generateViewport— nextjs.org/docs/app/api-reference/functions/generate-metadata (2026-10-21 da o'qildi) - Kanon natijalari:
natijalar/30-seo.txt,natijalar/tajriba/37-env-instrumentation.txt,natijalar/tajriba/38-lighthouse-sayt-url-lokal.txt; holat 30 diff metadata+generateMetadataxatosi vaopenGraphalmashtirish HTML'i — biz ishga tushirdik:portfolioholat 32 nusxasi,next dev, next 16.4.0, 2026-10-21- Open Graph protokoli: ogp.me
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!