generateMetadata
يمكنك استخدام كائن metadata
أو دالة generateMetadata
لتعريف البيانات الوصفية.
كائن metadata
لتعريف بيانات وصفية ثابتة، قم بتصدير كائن Metadata
من ملف layout.js
أو page.js
.
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: '...',
description: '...',
}
export default function Page() {}
export const metadata = {
title: '...',
description: '...',
}
export default function Page() {}
راجع حقول البيانات الوصفية للحصول على قائمة كاملة بالخيارات المدعومة.
دالة generateMetadata
يمكن تعيين البيانات الوصفية الديناميكية التي تعتمد على معلومات ديناميكية، مثل معلمات المسار الحالية أو البيانات الخارجية أو metadata
في الأجزاء الأصلية، عن طريق تصدير دالة generateMetadata
تُرجع كائن Metadata
.
import type { Metadata, ResolvingMetadata } from 'next'
type Props = {
params: Promise<{ id: string }>
searchParams: Promise<{ [key: string]: string | string[] | undefined }>
}
export async function generateMetadata(
{ params, searchParams }: Props,
parent: ResolvingMetadata
): Promise<Metadata> {
// قراءة معلمات المسار
const { id } = await params
// جلب البيانات
const product = await fetch(`https://.../${id}`).then((res) => res.json())
// الوصول الاختياري إلى البيانات الوصفية الأصلية وتوسيعها (بدلاً من استبدالها)
const previousImages = (await parent).openGraph?.images || []
return {
title: product.title,
openGraph: {
images: ['/some-specific-page-image.jpg', ...previousImages],
},
}
}
export default function Page({ params, searchParams }: Props) {}
export async function generateMetadata({ params, searchParams }, parent) {
// قراءة معلمات المسار
const { id } = await params
// جلب البيانات
const product = await fetch(`https://.../${id}`).then((res) => res.json())
// الوصول الاختياري إلى البيانات الوصفية الأصلية وتوسيعها (بدلاً من استبدالها)
const previousImages = (await parent).openGraph?.images || []
return {
title: product.title,
openGraph: {
images: ['/some-specific-page-image.jpg', ...previousImages],
},
}
}
export default function Page({ params, searchParams }) {}
ملاحظة جيدة:
- يمكن إضافة البيانات الوصفية إلى ملفات
layout.js
وpage.js
.- سيقوم Next.js بحل البيانات الوصفية تلقائيًا وإنشاء علامات
<head>
ذات الصلة للصفحة.- تصديرات كائن
metadata
ودالةgenerateMetadata
مدعومة فقط في مكونات الخادم (Server Components).- لا يمكنك تصدير كل من كائن
metadata
ودالةgenerateMetadata
من نفس مقطع المسار.- طلبات
fetch
داخلgenerateMetadata
يتم تخزينها مؤقتًا تلقائيًا لنفس البيانات عبرgenerateMetadata
وgenerateStaticParams
والتخطيطات والصفحات ومكونات الخادم.- يمكن استخدام
cache
في React إذا كانfetch
غير متاح.- البيانات الوصفية المستندة إلى الملفات لها الأولوية الأعلى وستتجاوز كائن
metadata
ودالةgenerateMetadata
.
المرجع
المعاملات
تقبل دالة generateMetadata
المعاملات التالية:
-
props
- كائن يحتوي على معلمات المسار الحالي:-
params
- كائن يحتوي على معلمات المسار الديناميكي من المقطع الجذري وصولاً إلى المقطع الذي يتم استدعاءgenerateMetadata
منه. أمثلة:المسار الرابط params
app/shop/[slug]/page.js
/shop/1
{ slug: '1' }
app/shop/[tag]/[item]/page.js
/shop/1/2
{ tag: '1', item: '2' }
app/shop/[...slug]/page.js
/shop/1/2
{ slug: ['1', '2'] }
-
searchParams
- كائن يحتوي على معلمات البحث (search params) للرابط الحالي. أمثلة:الرابط searchParams
/shop?a=1
{ a: '1' }
/shop?a=1&b=2
{ a: '1', b: '2' }
/shop?a=1&a=2
{ a: ['1', '2'] }
-
-
parent
- وعد بحل البيانات الوصفية من مقاطع المسار الأصلية.
القيم المرجعة
يجب أن تُرجع generateMetadata
كائن Metadata
يحتوي على حقل بيانات وصفية واحد أو أكثر.
ملاحظة جيدة:
- إذا كانت البيانات الوصفية لا تعتمد على معلومات وقت التشغيل، فيجب تعريفها باستخدام كائن
metadata
الثابت بدلاً منgenerateMetadata
.- يتم تخزين طلبات
fetch
مؤقتًا تلقائيًا لنفس البيانات عبرgenerateMetadata
وgenerateStaticParams
والتخطيطات والصفحات ومكونات الخادم. يمكن استخدامcache
في React إذا كانfetch
غير متاح.searchParams
متاحة فقط في مقاطعpage.js
.- يمكن أيضًا استخدام طرق Next.js
redirect()
وnotFound()
داخلgenerateMetadata
.
حقول البيانات الوصفية
الحقول التالية مدعومة:
title
يُستخدم سمة title
لتعيين عنوان المستند. يمكن تعريفه كـ سلسلة نصية بسيطة أو كائن قالب اختياري.
سلسلة نصية
export const metadata = {
title: 'Next.js',
}
<title>Next.js</title>
default
يمكن استخدام title.default
لتوفير عنوان احتياطي لمقاطع المسار الفرعية التي لا تحدد title
.
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: {
default: 'Acme',
},
}
import type { Metadata } from 'next'
export const metadata: Metadata = {}
// الناتج: <title>Acme</title>
template
يمكن استخدام title.template
لإضافة بادئة أو لاحقة إلى titles
المحددة في مقاطع المسار الفرعية.
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: {
template: '%s | Acme',
default: 'Acme', // مطلوب قيمة افتراضية عند إنشاء قالب
},
}
export const metadata = {
title: {
template: '%s | Acme',
default: 'Acme', // مطلوب قيمة افتراضية عند إنشاء قالب
},
}
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'About',
}
// الناتج: <title>About | Acme</title>
export const metadata = {
title: 'About',
}
// الناتج: <title>About | Acme</title>
ملاحظة جيدة:
title.template
ينطبق على مقاطع المسار الفرعية وليس المقطع الذي تم تعريفه فيه. هذا يعني:
title.default
مطلوب عند إضافةtitle.template
.- لن ينطبق
title.template
المحدد فيlayout.js
علىtitle
المحدد فيpage.js
لنفس مقطع المسار.title.template
المحدد فيpage.js
ليس له تأثير لأن الصفحة دائمًا ما تكون المقطع النهائي (ليس لديها أي مقاطع مسار فرعية).
title.template
ليس له تأثير إذا لم يحدد المسارtitle
أوtitle.default
.
absolute
يمكن استخدام title.absolute
لتوفير عنوان يتجاهل title.template
المحدد في المقاطع الأصلية.
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: {
template: '%s | Acme',
},
}
export const metadata = {
title: {
template: '%s | Acme',
},
}
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: {
absolute: 'About',
},
}
// الناتج: <title>About</title>
export const metadata = {
title: {
absolute: 'About',
},
}
// الناتج: <title>About</title>
ملاحظة جيدة:
layout.js
title
(سلسلة نصية) وtitle.default
يحددان العنوان الافتراضي للمقاطع الفرعية (التي لا تحددtitle
الخاصة بها). سيعززtitle.template
من أقرب مقطع أصل إذا كان موجودًا.title.absolute
يحدد العنوان الافتراضي للمقاطع الفرعية. يتجاهلtitle.template
من المقاطع الأصلية.title.template
يحدد قالب عنوان جديد للمقاطع الفرعية.
page.js
- إذا لم تحدد الصفحة عنوانها الخاص، سيتم استخدام العنوان المحلول لأقرب مقطع أصل.
title
(سلسلة نصية) يحدد عنوان المسار. سيعززtitle.template
من أقرب مقطع أصل إذا كان موجودًا.title.absolute
يحدد عنوان المسار. يتجاهلtitle.template
من المقاطع الأصلية.title.template
ليس له تأثير فيpage.js
لأن الصفحة دائمًا ما تكون المقطع النهائي للمسار.
description
export const metadata = {
description: 'إطار عمل React للويب',
}
<meta name="description" content="إطار عمل React للويب" />
حقول أخرى
export const metadata = {
generator: 'Next.js',
applicationName: 'Next.js',
referrer: 'origin-when-cross-origin',
keywords: ['Next.js', 'React', 'JavaScript'],
authors: [{ name: 'Seb' }, { name: 'Josh', url: 'https://nextjs.org' }],
creator: 'Jiachi Liu',
publisher: 'Sebastian Markbåge',
formatDetection: {
email: false,
address: false,
telephone: false,
},
}
<meta name="application-name" content="Next.js" />
<meta name="author" content="Seb" />
<link rel="author" href="https://nextjs.org" />
<meta name="author" content="Josh" />
<meta name="generator" content="Next.js" />
<meta name="keywords" content="Next.js,React,JavaScript" />
<meta name="referrer" content="origin-when-cross-origin" />
<meta name="color-scheme" content="dark" />
<meta name="creator" content="Jiachi Liu" />
<meta name="publisher" content="Sebastian Markbåge" />
<meta name="format-detection" content="telephone=no, address=no, email=no" />
metadataBase
metadataBase
هو خيار ملائم لتعيين بادئة عنوان URL أساسي لحقول metadata
التي تتطلب عنوان URL مؤهلًا بالكامل.
- يسمح
metadataBase
لحقولmetadata
المستندة إلى URL المحددة في مقطع المسار الحالي وما دونه باستخدام مسار نسبي بدلاً من عنوان URL المطلق المطلوب. - سيتم دمج المسار النسبي للحقل مع
metadataBase
لتشكيل عنوان URL مؤهل بالكامل.
export const metadata = {
metadataBase: new URL('https://acme.com'),
alternates: {
canonical: '/',
languages: {
'en-US': '/en-US',
'de-DE': '/de-DE',
},
},
openGraph: {
images: '/og-image.png',
},
}
<link rel="canonical" href="https://acme.com" />
<link rel="alternate" hreflang="en-US" href="https://acme.com/en-US" />
<link rel="alternate" hreflang="de-DE" href="https://acme.com/de-DE" />
<meta property="og:image" content="https://acme.com/og-image.png" />
ملاحظة جيدة:
- يتم تعيين
metadataBase
عادةً فيapp/layout.js
الجذر لتطبيق حقولmetadata
المستندة إلى URL عبر جميع المسارات.- يمكن تكوين جميع حقول
metadata
المستندة إلى URL التي تتطلب عناوين URL مطلقة باستخدام خيارmetadataBase
.- يمكن أن يحتوي
metadataBase
على نطاق فرعي مثلhttps://app.acme.com
أو مسار أساسي مثلhttps://acme.com/start/from/here
- إذا قدم حقل
metadata
عنوان URL مطلقًا، سيتم تجاهلmetadataBase
.- سيؤدي استخدام مسار نسبي في حقل
metadata
مستند إلى URL بدون تكوينmetadataBase
إلى حدوث خطأ في البناء.- سيقوم Next.js بتطبيع الشرطات المكررة بين
metadataBase
(مثلhttps://acme.com/
) وحقل نسبي (مثل/path
) إلى شرطة واحدة (مثلhttps://acme.com/path
)
تكوين URL
يفضل تكوين URL نية المطور على دلالات اجتياز الدليل الافتراضية.
- يتم تطبيع الشرطات في نهاية
metadataBase
وحقولmetadata
. - يتم التعامل مع المسار "المطلق" في حقل
metadata
(الذي عادةً ما يستبدل مسار URL بالكامل) على أنه مسار "نسبي" (يبدأ من نهايةmetadataBase
).
على سبيل المثال، بالنظر إلى metadataBase
التالي:
import type { Metadata } from 'next'
export const metadata: Metadata = {
metadataBase: new URL('https://acme.com'),
}
export const metadata = {
metadataBase: new URL('https://acme.com'),
}
سيتم حل أي حقول metadata
التي ترث metadataBase
أعلاه وتعيين قيمتها الخاصة على النحو التالي:
حقل metadata | عنوان URL المحلول |
---|---|
/ | https://acme.com |
./ | https://acme.com |
payments | https://acme.com/payments |
/payments | https://acme.com/payments |
./payments | https://acme.com/payments |
../payments | https://acme.com/payments |
https://beta.acme.com/payments | https://beta.acme.com/payments |
openGraph
export const metadata = {
openGraph: {
title: 'Next.js',
description: 'The React Framework for the Web',
url: 'https://nextjs.org',
siteName: 'Next.js',
images: [
{
url: 'https://nextjs.org/og.png', // يجب أن يكون عنوان URL مطلقًا
width: 800,
height: 600,
},
{
url: 'https://nextjs.org/og-alt.png', // يجب أن يكون عنوان URL مطلقًا
width: 1800,
height: 1600,
alt: 'النص البديل المخصص',
},
],
videos: [
{
url: 'https://nextjs.org/video.mp4', // يجب أن يكون عنوان URL مطلقًا
width: 800,
height: 600,
},
],
audio: [
{
url: 'https://nextjs.org/audio.mp3', // يجب أن يكون عنوان URL مطلقًا
},
],
locale: 'en_US',
type: 'website',
},
}
<meta property="og:title" content="Next.js" />
<meta property="og:description" content="The React Framework for the Web" />
<meta property="og:url" content="https://nextjs.org/" />
<meta property="og:site_name" content="Next.js" />
<meta property="og:locale" content="en_US" />
<meta property="og:image" content="https://nextjs.org/og.png" />
<meta property="og:image:width" content="800" />
<meta property="og:image:height" content="600" />
<meta property="og:image" content="https://nextjs.org/og-alt.png" />
<meta property="og:image:width" content="1800" />
<meta property="og:image:height" content="1600" />
<meta property="og:image:alt" content="النص البديل المخصص" />
<meta property="og:video" content="https://nextjs.org/video.mp4" />
<meta property="og:video:width" content="800" />
<meta property="og:video:height" content="600" />
<meta property="og:audio" content="https://nextjs.org/audio.mp3" />
<meta property="og:type" content="website" />
export const metadata = {
openGraph: {
title: 'Next.js',
description: 'The React Framework for the Web',
type: 'article',
publishedTime: '2023-01-01T00:00:00.000Z',
authors: ['Seb', 'Josh'],
},
}
<meta property="og:title" content="Next.js" />
<meta property="og:description" content="The React Framework for the Web" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2023-01-01T00:00:00.000Z" />
<meta property="article:author" content="Seb" />
<meta property="article:author" content="Josh" />
معلومة مفيدة:
- قد يكون استخدام واجهة برمجة تطبيق Metadata المعتمدة على الملفات لصور Open Graph أكثر ملاءمة. بدلاً من الحاجة إلى مزامنة تصدير التكوين مع الملفات الفعلية، ستقوم واجهة برمجة التطبيق المعتمدة على الملفات بإنشاء بيانات التعريف الصحيحة تلقائيًا لك.
robots
import type { Metadata } from 'next'
export const metadata: Metadata = {
robots: {
index: true,
follow: true,
nocache: false,
googleBot: {
index: true,
follow: true,
noimageindex: false,
'max-video-preview': -1,
'max-image-preview': 'large',
'max-snippet': -1,
},
},
}
<meta name="robots" content="index, follow" />
<meta
name="googlebot"
content="index, follow, max-video-preview:-1, max-image-preview:large, max-snippet:-1"
/>
icons
معلومة مفيدة: نوصي باستخدام واجهة برمجة تطبيق Metadata المعتمدة على الملفات للأيقونات حيثما أمكن ذلك. بدلاً من الحاجة إلى مزامنة تصدير التكوين مع الملفات الفعلية، ستقوم واجهة برمجة التطبيق المعتمدة على الملفات بإنشاء بيانات التعريف الصحيحة تلقائيًا لك.
export const metadata = {
icons: {
icon: '/icon.png',
shortcut: '/shortcut-icon.png',
apple: '/apple-icon.png',
other: {
rel: 'apple-touch-icon-precomposed',
url: '/apple-touch-icon-precomposed.png',
},
},
}
<link rel="shortcut icon" href="/shortcut-icon.png" />
<link rel="icon" href="/icon.png" />
<link rel="apple-touch-icon" href="/apple-icon.png" />
<link
rel="apple-touch-icon-precomposed"
href="/apple-touch-icon-precomposed.png"
/>
export const metadata = {
icons: {
icon: [
{ url: '/icon.png' },
new URL('/icon.png', 'https://example.com'),
{ url: '/icon-dark.png', media: '(prefers-color-scheme: dark)' },
],
shortcut: ['/shortcut-icon.png'],
apple: [
{ url: '/apple-icon.png' },
{ url: '/apple-icon-x3.png', sizes: '180x180', type: 'image/png' },
],
other: [
{
rel: 'apple-touch-icon-precomposed',
url: '/apple-touch-icon-precomposed.png',
},
],
},
}
<link rel="shortcut icon" href="/shortcut-icon.png" />
<link rel="icon" href="/icon.png" />
<link rel="icon" href="https://example.com/icon.png" />
<link rel="icon" href="/icon-dark.png" media="(prefers-color-scheme: dark)" />
<link rel="apple-touch-icon" href="/apple-icon.png" />
<link
rel="apple-touch-icon-precomposed"
href="/apple-touch-icon-precomposed.png"
/>
<link
rel="apple-touch-icon"
href="/apple-icon-x3.png"
sizes="180x180"
type="image/png"
/>
معلومة مفيدة: لم تعد علامات meta من نوع
msapplication-*
مدعومة في إصدارات Chromium من Microsoft Edge، وبالتالي لم تعد هناك حاجة إليها.
themeColor
مهمل: خيار
themeColor
فيmetadata
مهمل اعتبارًا من Next.js 14. يرجى استخدام تكوين viewport بدلاً من ذلك.
colorScheme
مهمل: خيار
colorScheme
فيmetadata
مهمل اعتبارًا من Next.js 14. يرجى استخدام تكوين viewport بدلاً من ذلك.
manifest
بيان تطبيق ويب، كما هو محدد في مواصفات بيان تطبيق الويب.
export const metadata = {
manifest: 'https://nextjs.org/manifest.json',
}
<link rel="manifest" href="https://nextjs.org/manifest.json" />
twitter
تستخدم مواصفات تويتر (بشكل مفاجئ) لأكثر من مجرد X (المعروف سابقًا باسم تويتر).
تعرف على المزيد حول مرجع ترميز بطاقة تويتر.
export const metadata = {
twitter: {
card: 'summary_large_image',
title: 'Next.js',
description: 'The React Framework for the Web',
siteId: '1467726470533754880',
creator: '@nextjs',
creatorId: '1467726470533754880',
images: ['https://nextjs.org/og.png'], // يجب أن يكون عنوان URL مطلقًا
},
}
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site:id" content="1467726470533754880" />
<meta name="twitter:creator" content="@nextjs" />
<meta name="twitter:creator:id" content="1467726470533754880" />
<meta name="twitter:title" content="Next.js" />
<meta name="twitter:description" content="The React Framework for the Web" />
<meta name="twitter:image" content="https://nextjs.org/og.png" />
export const metadata = {
twitter: {
card: 'app',
title: 'Next.js',
description: 'The React Framework for the Web',
siteId: '1467726470533754880',
creator: '@nextjs',
creatorId: '1467726470533754880',
images: {
url: 'https://nextjs.org/og.png',
alt: 'شعار Next.js',
},
app: {
name: 'twitter_app',
id: {
iphone: 'twitter_app://iphone',
ipad: 'twitter_app://ipad',
googleplay: 'twitter_app://googleplay',
},
url: {
iphone: 'https://iphone_url',
ipad: 'https://ipad_url',
},
},
},
}
<meta name="twitter:site:id" content="1467726470533754880" />
<meta name="twitter:creator" content="@nextjs" />
<meta name="twitter:creator:id" content="1467726470533754880" />
<meta name="twitter:title" content="Next.js" />
<meta name="twitter:description" content="The React Framework for the Web" />
<meta name="twitter:card" content="app" />
<meta name="twitter:image" content="https://nextjs.org/og.png" />
<meta name="twitter:image:alt" content="شعار Next.js" />
<meta name="twitter:app:name:iphone" content="twitter_app" />
<meta name="twitter:app:id:iphone" content="twitter_app://iphone" />
<meta name="twitter:app:id:ipad" content="twitter_app://ipad" />
<meta name="twitter:app:id:googleplay" content="twitter_app://googleplay" />
<meta name="twitter:app:url:iphone" content="https://iphone_url" />
<meta name="twitter:app:url:ipad" content="https://ipad_url" />
<meta name="twitter:app:name:ipad" content="twitter_app" />
<meta name="twitter:app:name:googleplay" content="twitter_app" />
viewport
مهمل: خيار
viewport
فيmetadata
مهمل اعتبارًا من Next.js 14. يرجى استخدام تكوين viewport بدلاً من ذلك.
verification
export const metadata = {
verification: {
google: 'google',
yandex: 'yandex',
yahoo: 'yahoo',
other: {
me: ['my-email', 'my-link'],
},
},
}
<meta name="google-site-verification" content="google" />
<meta name="y_key" content="yahoo" />
<meta name="yandex-verification" content="yandex" />
<meta name="me" content="my-email" />
<meta name="me" content="my-link" />
appleWebApp
export const metadata = {
itunes: {
appId: 'myAppStoreID',
appArgument: 'myAppArgument',
},
appleWebApp: {
title: 'تطبيق ويب Apple',
statusBarStyle: 'black-translucent',
startupImage: [
'/assets/startup/apple-touch-startup-image-768x1004.png',
{
url: '/assets/startup/apple-touch-startup-image-1536x2008.png',
media: '(device-width: 768px) and (device-height: 1024px)',
},
],
},
}
<meta
name="apple-itunes-app"
content="app-id=myAppStoreID, app-argument=myAppArgument"
/>
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-title" content="تطبيق ويب Apple" />
<link
href="/assets/startup/apple-touch-startup-image-768x1004.png"
rel="apple-touch-startup-image"
/>
<link
href="/assets/startup/apple-touch-startup-image-1536x2008.png"
media="(device-width: 768px) and (device-height: 1024px)"
rel="apple-touch-startup-image"
/>
<meta
name="apple-mobile-web-app-status-bar-style"
content="black-translucent"
/>
alternates
export const metadata = {
alternates: {
canonical: 'https://nextjs.org',
languages: {
'en-US': 'https://nextjs.org/en-US',
'de-DE': 'https://nextjs.org/de-DE',
},
media: {
'only screen and (max-width: 600px)': 'https://nextjs.org/mobile',
},
types: {
'application/rss+xml': 'https://nextjs.org/rss',
},
},
}
<link rel="canonical" href="https://nextjs.org" />
<link rel="alternate" hreflang="en-US" href="https://nextjs.org/en-US" />
<link rel="alternate" hreflang="de-DE" href="https://nextjs.org/de-DE" />
<link
rel="alternate"
media="only screen and (max-width: 600px)"
href="https://nextjs.org/mobile"
/>
<link
rel="alternate"
type="application/rss+xml"
href="https://nextjs.org/rss"
/>
appLinks
export const metadata = {
appLinks: {
ios: {
url: 'https://nextjs.org/ios',
app_store_id: 'app_store_id',
},
android: {
package: 'com.example.android/package',
app_name: 'app_name_android',
},
web: {
url: 'https://nextjs.org/web',
should_fallback: true,
},
},
}
<meta property="al:ios:url" content="https://nextjs.org/ios" />
<meta property="al:ios:app_store_id" content="app_store_id" />
<meta property="al:android:package" content="com.example.android/package" />
<meta property="al:android:app_name" content="app_name_android" />
<meta property="al:web:url" content="https://nextjs.org/web" />
<meta property="al:web:should_fallback" content="true" />
archives
يصف مجموعة من السجلات أو المستندات أو المواد الأخرى ذات الأهمية التاريخية (المصدر).
export const metadata = {
archives: ['https://nextjs.org/13'],
}
<link rel="archives" href="https://nextjs.org/13" />
assets
export const metadata = {
assets: ['https://nextjs.org/assets'],
}
<link rel="assets" href="https://nextjs.org/assets" />
bookmarks
export const metadata = {
bookmarks: ['https://nextjs.org/13'],
}
<link rel="bookmarks" href="https://nextjs.org/13" />
category
export const metadata = {
category: 'technology',
}
<meta name="category" content="technology" />
facebook
يمكنك توصيل تطبيق Facebook أو حساب Facebook بصفحة الويب الخاصة بك لبعض ملحقات Facebook الاجتماعية توثيق Facebook
معلومة مفيدة: يمكنك تحديد إما appId أو admins، ولكن ليس كلاهما.
export const metadata = {
facebook: {
appId: '12345678',
},
}
<meta property="fb:app_id" content="12345678" />
export const metadata = {
facebook: {
admins: '12345678',
},
}
<meta property="fb:admins" content="12345678" />
إذا كنت تريد إنشاء علامات meta متعددة لـ fb:admins، يمكنك استخدام قيمة مصفوفة.
export const metadata = {
facebook: {
admins: ['12345678', '87654321'],
},
}
<meta property="fb:admins" content="12345678" />
<meta property="fb:admins" content="87654321" />
pinterest
يمكنك تمكين أو تعطيل Pinterest Rich Pins على صفحة الويب الخاصة بك.
export const metadata = {
pinterest: {
richPin: true,
},
}
<meta name="pinterest-rich-pin" content="true" />
other
يجب أن تغطي خيارات بيانات التعريف المدمجة جميع الاحتياجات. ومع ذلك، قد تكون هناك علامات بيانات تعريف مخصصة خاصة بموقعك، أو علامات بيانات تعريف جديدة تم إصدارها للتو. يمكنك استخدام خيار other
لعرض أي علامة بيانات تعريف مخصصة.
export const metadata = {
other: {
custom: 'meta',
},
}
<meta name="custom" content="meta" />
إذا كنت تريد إنشاء علامات meta متعددة بنفس المفتاح، يمكنك استخدام قيمة مصفوفة.
export const metadata = {
other: {
custom: ['meta1', 'meta2'],
},
}
<meta name="custom" content="meta1" /> <meta name="custom" content="meta2" />
بيانات التعريف غير المدعومة
لا يوجد حاليًا دعم مدمج لأنواع بيانات التعريف التالية. ومع ذلك، لا يزال يمكن عرضها في التخطيط أو الصفحة نفسها.
الأنواع
يمكنك إضافة أمان النوع إلى البيانات الوصفية (metadata) باستخدام نوع Metadata
. إذا كنت تستخدم ملحق TypeScript المدمج في بيئة التطوير الخاصة بك، فلن تحتاج إلى إضافة النوع يدويًا، ولكن يمكنك إضافة ذلك بشكل صريح إذا أردت.
كائن metadata
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'Next.js',
}
دالة generateMetadata
دالة عادية
import type { Metadata } from 'next'
export function generateMetadata(): Metadata {
return {
title: 'Next.js',
}
}
دالة غير متزامنة (Async)
import type { Metadata } from 'next'
export async function generateMetadata(): Promise<Metadata> {
return {
title: 'Next.js',
}
}
مع خاصية القطعة (segment props)
import type { Metadata } from 'next'
type Props = {
params: Promise<{ id: string }>
searchParams: Promise<{ [key: string]: string | string[] | undefined }>
}
export function generateMetadata({ params, searchParams }: Props): Metadata {
return {
title: 'Next.js',
}
}
export default function Page({ params, searchParams }: Props) {}
مع البيانات الوصفية الأصلية (parent metadata)
import type { Metadata, ResolvingMetadata } from 'next'
export async function generateMetadata(
{ params, searchParams }: Props,
parent: ResolvingMetadata
): Promise<Metadata> {
return {
title: 'Next.js',
}
}
مشاريع JavaScript
لمشاريع JavaScript، يمكنك استخدام JSDoc لإضافة أمان النوع.
/** @type {import("next").Metadata} */
export const metadata = {
title: 'Next.js',
}
البيانات الوصفية | التوصية |
---|---|
<meta http-equiv="..."> | استخدم رؤوس HTTP المناسبة عبر redirect() ، البرمجية الوسيطة (Middleware)، رؤوس الأمان |
<base> | عرض العلامة في التنسيق (layout) أو الصفحة نفسها. |
<noscript> | عرض العلامة في التنسيق أو الصفحة نفسها. |
<style> | تعلم المزيد حول التنسيق في Next.js. |
<script> | تعلم المزيد حول استخدام النصوص البرمجية (scripts). |
<link rel="stylesheet" /> | import أوراق الأنماط مباشرة في التنسيق أو الصفحة نفسها. |
<link rel="preload /> | استخدم طريقة ReactDOM المسبقة (preload method) |
<link rel="preconnect" /> | استخدم طريقة ReactDOM للاتصال المسبق (preconnect method) |
<link rel="dns-prefetch" /> | استخدم طريقة ReactDOM للبحث المسبق عن DNS (prefetchDNS method) |
تلميحات الموارد (Resource hints)
يحتوي عنصر <link>
على عدد من الكلمات الرئيسية rel
التي يمكن استخدامها للإشارة إلى المتصفح بأن موردًا خارجيًا قد يكون مطلوبًا. يستخدم المتصفح هذه المعلومات لتطبيق تحسينات التحميل المسبق اعتمادًا على الكلمة الرئيسية.
بينما لا تدعم واجهة برمجة تطبيق البيانات الوصفية هذه التلميحات مباشرة، يمكنك استخدام طرق ReactDOM
الجديدة لإدراجها بأمان في <head>
المستند.
'use client'
import ReactDOM from 'react-dom'
export function PreloadResources() {
ReactDOM.preload('...', { as: '...' })
ReactDOM.preconnect('...', { crossOrigin: '...' })
ReactDOM.prefetchDNS('...')
return '...'
}
'use client'
import ReactDOM from 'react-dom'
export function PreloadResources() {
ReactDOM.preload('...', { as: '...' })
ReactDOM.preconnect('...', { crossOrigin: '...' })
ReactDOM.prefetchDNS('...')
return '...'
}
<link rel="preload">
ابدأ تحميل مورد في وقت مبكر من دورة حياة عرض الصفحة (في المتصفح). وثائق MDN.
ReactDOM.preload(href: string, options: { as: string })
<link rel="preload" href="..." as="..." />
<link rel="preconnect">
ابدأ اتصالًا مسبقًا بأصل (origin). وثائق MDN.
ReactDOM.preconnect(href: string, options?: { crossOrigin?: string })
<link rel="preconnect" href="..." crossorigin />
<link rel="dns-prefetch">
حاول حل اسم نطاق قبل طلب الموارد. وثائق MDN.
ReactDOM.prefetchDNS(href: string)
<link rel="dns-prefetch" href="..." />
معلومة جيدة:
- هذه الطرق مدعومة حاليًا فقط في مكونات العميل (Client Components)، والتي لا تزال تُعرض من جانب الخادم عند التحميل الأولي للصفحة.
- الميزات المدمجة في Next.js مثل
next/font
،next/image
وnext/script
تتعامل تلقائيًا مع تلميحات الموارد ذات الصلة.
السلوك
الحقول الافتراضية
هناك علامتا meta
افتراضيتان تُضافان دائمًا حتى إذا لم تحدد المسار بيانات وصفية:
- علامة meta charset تحدد ترميز الأحرف للموقع.
- علامة meta viewport تحدد عرض viewport ومقياسه للموقع للتكيف مع الأجهزة المختلفة.
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
معلومة جيدة: يمكنك تجاوز علامة
viewport
الافتراضية.
بث البيانات الوصفية (Streaming metadata)
يتم بث البيانات الوصفية التي تُرجعها generateMetadata
إلى العميل. هذا يسمح لـ Next.js بحقن البيانات الوصفية في HTML بمجرد حلها.
نظرًا لأن بيانات وصفية الصفحة تستهدف بشكل أساسي برامج الروبوت والمفهرسات، سيقوم Next.js ببث البيانات الوصفية للروبوتات التي يمكنها تنفيذ JavaScript وفحص DOM الصفحة بالكامل (مثل Googlebot
). ومع ذلك، ستستمر البيانات الوصفية في منع عرض الصفحة للروبوتات المحدودة بـ HTML (مثل Twitterbot
) حيث لا يمكنها تنفيذ JavaScript أثناء الزحف.
يتم اكتشاف وكيل المستخدم للطلبات الواردة تلقائيًا لتحديد ما إذا كان سيتم تقديم بيانات وصفية متدفقة أو التراجع إلى البيانات الوصفية الحاجزة.
إذا كنت بحاجة إلى تخصيص هذه القائمة، يمكنك تعريفها يدويًا باستخدام خيار htmlLimitedBots
في next.config.js
. سيتأكد Next.js من أن وكلاء المستخدم الذين يتطابقون مع هذا التعبير المنتظم يتلقون بيانات وصفية حاجزة عند طلب صفحة الويب الخاصة بك.
import type { NextConfig } from 'next'
const config: NextConfig = {
htmlLimitedBots: /MySpecialBot|MyAnotherSpecialBot|SimpleCrawler/,
}
export default config
module.exports = {
htmlLimitedBots: /MySpecialBot|MyAnotherSpecialBot|SimpleCrawler/,
}
سيؤدي تحديد تكوين htmlLimitedBots
إلى تجاوز القائمة الافتراضية لـ Next.js، مما يمنحك سيطرة كاملة على وكلاء المستخدم الذين يجب أن يختاروا هذا السلوك. هذا سلوك متقدم، ويجب أن يكون الافتراضي كافيًا لمعظم الحالات.
الترتيب
يتم تقييم البيانات الوصفية بالترتيب، بدءًا من القطعة الجذرية وصولاً إلى القطعة الأقرب إلى قطعة page.js
النهائية. على سبيل المثال:
app/layout.tsx
(التنسيق الجذري)app/blog/layout.tsx
(تنسيق المدونة المتداخل)app/blog/[slug]/page.tsx
(صفحة المدونة)
الدمج
بعد ترتيب التقييم، يتم دمج كائنات البيانات الوصفية المصدرة من عدة أجزاء في نفس المسار بشكل سطحي معًا لتشكيل ناتج البيانات الوصفية النهائي للمسار. يتم استبدال المفاتيح المكررة بناءً على ترتيبها.
هذا يعني أن البيانات الوصفية ذات الحقول المتداخلة مثل openGraph
و robots
التي تم تعريفها في جزء سابق يتم تجاوزها بواسطة الجزء الأخير الذي يحددها.
تجاوز الحقول
export const metadata = {
title: 'Acme',
openGraph: {
title: 'Acme',
description: 'Acme is a...',
},
}
export const metadata = {
title: 'Blog',
openGraph: {
title: 'Blog',
},
}
// الناتج:
// <title>Blog</title>
// <meta property="og:title" content="Blog" />
في المثال أعلاه:
- يتم استبدال
title
منapp/layout.js
بـtitle
فيapp/blog/page.js
. - يتم استبدال جميع حقول
openGraph
منapp/layout.js
فيapp/blog/page.js
لأنapp/blog/page.js
يحدد بياناتopenGraph
الوصفية. لاحظ غيابopenGraph.description
.
إذا كنت ترغب في مشاركة بعض الحقول المتداخلة بين الأجزاء أثناء تجاوز البعض الآخر، يمكنك استخراجها إلى متغير منفصل:
export const openGraphImage = { images: ['http://...'] }
import { openGraphImage } from './shared-metadata'
export const metadata = {
openGraph: {
...openGraphImage,
title: 'Home',
},
}
import { openGraphImage } from '../shared-metadata'
export const metadata = {
openGraph: {
...openGraphImage,
title: 'About',
},
}
في المثال أعلاه، يتم مشاركة صورة OG بين app/layout.js
و app/about/page.js
بينما تختلف العناوين.
وراثة الحقول
export const metadata = {
title: 'Acme',
openGraph: {
title: 'Acme',
description: 'Acme is a...',
},
}
export const metadata = {
title: 'About',
}
// الناتج:
// <title>About</title>
// <meta property="og:title" content="Acme" />
// <meta property="og:description" content="Acme is a..." />
ملاحظات
- يتم استبدال
title
منapp/layout.js
بـtitle
فيapp/about/page.js
. - يتم وراثة جميع حقول
openGraph
منapp/layout.js
فيapp/about/page.js
لأنapp/about/page.js
لا يحدد بياناتopenGraph
الوصفية.
سجل الإصدارات
الإصدار | التغييرات |
---|---|
v15.2.0 | تم تقديم دعم البث لـ generateMetadata . |
v13.2.0 | تم إهمال viewport ، themeColor ، و colorScheme لصالح تكوين viewport . |
v13.2.0 | تم تقديم metadata و generateMetadata . |