IlmHamroh
JavaScript Full-stack/23-qism. Next.js29/43-dars16 daqiqa
Mundarija (28)

Next.js Metadata API: title shabloni, canonical, Open Graph va viewport

Qisqacha: Next.js'da <head> qo'lda yozilmaydi. layout.tsx yoki page.tsx dan export const metadata = { … } (o'zgarmas) yoki export 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: sahifadagi openGraph layout'dagi openGraph ni butunlay almashtiradi. themeColor kabi qiymatlar alohida viewport eksportida.

Bu darsda

  • metadata va generateMetadata farqini va ikkalasini birga yozib bo'lmasligini (haqiqiy xato) bilasiz.
  • title.template bilan har sahifaga " — Aziz Karimov" qo'shimchasini bir joydan berasiz.
  • metadataBase, alternates.canonical va canonical'ning meros tuzog'ini tushuntirasiz.
  • Open Graph va Twitter teglarini yozasiz va openGraph almashtirish tuzog'ini haqiqiy HTML bilan ko'rasiz.
  • viewport eksporti 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:

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

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

tsx
export const metadata: Metadata = { title: "Bir" };

export async function generateMetadata(): Promise<Metadata> {
  return { title: "Ikki" };
}
text
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/metadata

Tarjimasi: "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):

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

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

text
Aloqa — Aziz Karimov
Vazifalar ilovasi — skrinshot — Aziz Karimov
Aziz Karimov — frontend dasturchi

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

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

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

text
/: {"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):

text
## 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 metadataBase siz nisbiy og:image ni o'zi to'ldirib qo'ya olmaydi — axir so'rovning Host sarlavhasi 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):

text
<title>Aloqa — Aziz Karimov</title>
<meta property="og:title" content="Aloqa — Aziz Karimov"/>
<meta property="og:description" content="Aziz Karimov bilan bog&#x27;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):

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

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

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

ts
// 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:

tsx
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: robots ham ichma-ich obyekt ({ index, follow }). Layout robots: { index: true, follow: true }, sahifa robots: { index: false } bersa, sahifadagi follow qanday 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:

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

tsx
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

bash
npm run lint
npm run tip
npm run build
npm run start

Brauzerda 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 params va 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
js
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:

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

text
OK: /
OK: /aloqa
XATO: /loyihalar/vazifalar/rasm — canonical https://example.com
OK: /yoq

Uchinchi 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 metadataBase va title.template — birinchi qatorlardan. Ko'p jamoalar OG_ASOS kabi umumiy obyekt yoki buildMetadata() yordamchisini yozadi.
  • E-commerce: mahsulot sahifasi generateMetadata da 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.template sarlavha qo'shimchasini bir joydan beradi; o'z segmentiga qo'llanmaydi, shuning uchun default majburiy.
  • metadataBase nisbiy manzillarni to'liq qiladi; canonical root layout'da bo'lsa hamma sahifaga meros bo'ladi — faqat bosh sahifada.
  • Metadata yuzaki birlashadi: sahifadagi openGraph layout'nikini butunlay almashtiradi — ...OG_ASOS naqshi.
  • viewport alohida eksport; statik sahifa metadata'si (va SAYT_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 + generateMetadata xatosi va openGraph almashtirish HTML'i — biz ishga tushirdik: portfolio holat 32 nusxasi, next dev, next 16.4.0, 2026-10-21
  • Open Graph protokoli: ogp.me
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Next.js Metadata API: title shabloni, canonical, Open Graph va viewport — IlmHamroh