العودة إلى المدونة

تحسين محركات البحث تقنيًا في Next.js App Router: قائمة عملية

تحسين محركات البحث تقنيًا في Next.js App Router: قائمة عملية

9 أكتوبر 2026 — SEO

تاريخ النشر

9 أكتوبر 2026

مدة القراءة

3 دقيقة للقراءة

التصنيف

SEO

الوسوم

  • SEO
  • Next.js
  • App Router
  • Metadata
  • Structured Data

(مقدمة)البيانات الوصفية، والروابط الأساسية (canonical)، وخرائط الموقع، وملف robots.txt، والبيانات المنظمة، وhreflang، ومؤشرات أداء الويب في Next.js App Router، مع شيفرة جاهزة للنسخ.

يمنحك Next.js كل ما تحتاجه لتحسين محركات البحث تقنيًا، لكن لا شيء تقريبًا منه مفعّل افتراضيًا. هذه هي القائمة التي أراجعها في كل مشروع App Router، مرتبة تقريبًا حسب الأثر.

1. اعرض المحتوى المهم على الخادم

تستطيع محركات البحث تشغيل JavaScript، لكنها تفهرس HTML المعروض على الخادم أسرع وبموثوقية أكبر. في App Router، مكونات الخادم هي الافتراضية؛ أبقِ فيها العناوين والنصوص والروابط، واستخدم مكونات العميل للتفاعل لا للمحتوى.

اختبار سريع: افتح صفحتك مع تعطيل JavaScript، أو شغّل curl https://yoursite.com/page. إن لم يكن النص الرئيسي في الاستجابة، فلن يكون في أول جولة فهرسة أيضًا.

2. اضبط metadataBase وقالبًا للعنوان

في التخطيط الجذري:

app/layout.tsx
import type { Metadata } from 'next'

export const metadata: Metadata = {
  metadataBase: new URL('https://example.com'),
  title: {
    default: 'Example Studio — Web Design and Development',
    template: '%s — Example Studio',
  },
  description: 'Websites and products for small teams: design, development and launch.',
  openGraph: { siteName: 'Example Studio', type: 'website' },
}

يحوّل metadataBase الروابط النسبية (الرابط الأساسي وصور Open Graph) إلى روابط مطلقة. وبفضل القالب، لا تضبط الصفحات الفرعية إلا جزءها من العنوان.

3. عنوان ووصف فريدان لكل صفحة

كل صفحة قابلة للفهرسة تحتاج إلى <title> خاص بها (نحو 50 إلى 60 حرفًا، والكلمة المفتاحية قرب البداية)، ووصف تعريفي خاص (نحو 150 إلى 160 حرفًا، مكتوب ليجذب النقر). وللصفحات الديناميكية استخدم generateMetadata:

app/blog/[slug]/page.tsx
export async function generateMetadata({ params }: { params: Promise<{ slug: string }> }) {
  const { slug } = await params
  const post = await getPost(slug)
  if (!post) return {}
  return {
    title: post.title,
    description: post.excerpt,
    alternates: { canonical: `/blog/${post.slug}` },
    openGraph: {
      type: 'article',
      publishedTime: post.date,
      images: [{ url: post.cover, width: 1200, height: 630 }],
    },
  }
}

4. الروابط الأساسية (Canonical)

اضبط alternates.canonical في كل صفحة. فهو يحميك من التكرار الناتج عن معاملات الرابط (?utm_source=...) والشرطة المائلة في النهاية والنطاقات البديلة. اختر صيغة واحدة (مع www أو بدونها، ومع الشرطة المائلة الأخيرة أو بدونها) ووجّه البقية إليها لدى المستضيف.

5. خريطة الموقع

يولّد app/sitemap.ts الملف /sitemap.xml، حتى مع التصدير الثابت:

app/sitemap.ts
import type { MetadataRoute } from 'next'
import { getAllPosts } from '@/lib/blog'

export const dynamic = 'force-static'

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  const base = 'https://example.com'
  const posts = await getAllPosts()
  return [
    { url: base, changeFrequency: 'monthly', priority: 1 },
    ...posts.map((post) => ({
      url: `${base}/blog/${post.slug}`,
      lastModified: post.date,
      changeFrequency: 'yearly' as const,
      priority: 0.7,
    })),
  ]
}

أرسلها مرة واحدة في Google Search Console وBing Webmaster Tools.

6. ملف robots.txt

app/robots.ts
import type { MetadataRoute } from 'next'

export const dynamic = 'force-static'

export default function robots(): MetadataRoute.Robots {
  return {
    rules: { userAgent: '*', allow: '/' },
    sitemap: 'https://example.com/sitemap.xml',
  }
}

لا تستخدم robots.txt لإخفاء الصفحات من الفهرس؛ فالصفحة المحظورة قد تُفهرس رغم ذلك من خلال الروابط. استخدم بدلًا منه robots: { index: false } في البيانات الوصفية للصفحة.

7. البيانات المنظمة (JSON-LD)

تساعد البيانات المنظمة محركات البحث على فهم ماهية الصفحة. للمقالة، اعرض وسم script داخل الصفحة:

tsx
const jsonLd = {
  '@context': 'https://schema.org',
  '@type': 'BlogPosting',
  headline: post.title,
  description: post.excerpt,
  datePublished: post.date,
  image: `https://example.com${post.cover}`,
  author: { '@type': 'Person', name: 'Jane Doe', url: 'https://example.com' },
}

return (
  <>
    <script
      type="application/ld+json"
      dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd).replace(/</g, '\\u003c') }}
    />
    <article>{/* ... */}</article>
  </>
)

أنواع مفيدة للشركات الصغيرة: Organization أو Person في الصفحة الرئيسية، وBlogPosting في المقالات، وBreadcrumbList في الصفحات العميقة، وProduct في صفحات المتجر. وتحقّق منها باختبار النتائج المنسّقة من Google.

8. صور Open Graph

الروابط المشاركة على LinkedIn وX وSlack وتطبيقات المراسلة تستخدم وسوم Open Graph. امنح كل صفحة صورة بمقاس 1200×630 بكسل. يمكنك وضع ملف opengraph-image.png ثابت بجوار الصفحة، أو توليد صورة باستخدام ImageResponse في opengraph-image.tsx (تُولَّد أثناء البناء في التصدير الثابت، فلا يمكن أن تعتمد على الطلب).

9. المواقع متعددة اللغات: روابط حقيقية وhreflang

كل لغة تحتاج إلى رابط خاص بها، وإلا فلن ترى محركات البحث إلا واحدة منها. تبديل اللغة في المتصفح عبر localStorage مناسب للزوار، لكنه غير مرئي لـ Google. استخدم مقطعًا للغة (app/[lang]/...) وصرّح بالبدائل:

ts
alternates: {
  canonical: '/en/blog/my-post',
  languages: {
    en: '/en/blog/my-post',
    'zh-CN': '/zh/blog/my-post',
    'sr-Latn': '/sr/blog/my-post',
    'x-default': '/en/blog/my-post',
  },
}

يجب أن تسرد كل نسخة لغوية جميع النسخ الأخرى، بما فيها نفسها.

10. الروابط الداخلية والعناوين

  • عنوان <h1> واحد في كل صفحة، ثم <h2>/<h3> بالترتيب. العناوين مخطط للمحتوى، لا حجم خط.
  • اربط الصفحات المترابطة ببعضها بنص رابط وصفي («دليل التصدير الثابت»، لا «انقر هنا»). استخدم <Link> لتكون الروابط عناصر <a href> حقيقية.
  • أبقِ الصفحات المهمة على بُعد ثلاث نقرات على الأكثر من الصفحة الرئيسية.

11. مؤشرات أداء الويب الأساسية

السرعة إشارة للترتيب، والأهم أنها إشارة للتحويل. قِس باستخدام PageSpeed Insights (البيانات الميدانية تأتي من مستخدمي Chrome الحقيقيين)، واستهدف LCP ≤ 2.5 ث، وINP ≤ 200 مللي ث، وCLS ≤ 0.1. المسببات المعتادة في App Router: صورة واجهة رئيسية ضخمة، وكثرة JavaScript في المتصفح، وإزاحة التخطيط بسبب خطوط أو صور بلا أبعاد. وإن كان موقعك كثير الحركة، فراجع مؤشرات أداء الويب للمواقع المتحركة.

12. الصور

  • نص alt وصفي للصور ذات المحتوى، وalt="" فارغ للصور الزخرفية.
  • width/height صريحة أو aspect-ratio لمنع إزاحة التخطيط.
  • صيغ حديثة (AVIF وWebP) وأحجام معقولة.
  • أسماء ملفات وصفية: nextjs-sitemap-example.png لا IMG_2041.png.

13. صفحات 404 وإعادة التوجيه

أعد خطأ 404 حقيقيًا للصفحات غير الموجودة (notFound() في App Router). وعند نقل الصفحات أو إعادة تسميتها، أضف إعادة توجيه 301 من الرابط القديم؛ وفي التصدير الثابت تكون قاعدة _redirects لدى المستضيف.

النسخة المختصرة

  • المحتوى في مكونات الخادم
  • metadataBase وقالب للعنوان في التخطيط الجذري
  • عنوان ووصف ورابط أساسي فريد لكل صفحة
  • sitemap.ts وrobots.ts، مع إرسال خريطة الموقع
  • JSON-LD للمقالات والجهة ومسار التنقل
  • صورة Open Graph لكل صفحة
  • رابط واحد لكل لغة، مع hreflang
  • عناوين منطقية وروابط داخلية وصفية
  • مؤشرات أداء الويب في المنطقة الخضراء
  • صفحات 404 حقيقية وإعادة توجيه 301 للصفحات المنقولة

تبني موقعًا ثابتًا؟ اقرأ دليل التصدير الثابت في Next.js للأجزاء التي تعمل بشكل مختلف دون خادم.

النشرة البريدية

تصلك المقالات الجديدة على بريدك

رسالة قصيرة عند نشر كل جديد. بلا رسائل مزعجة، ويمكنك إلغاء الاشتراك في أي وقت.

مدونة Markdown في Next.js دون نظام إدارة محتوى أو قاعدة بيانات
مدونة Markdown في Next.js دون نظام إدارة محتوى أو قاعدة بيانات
المقال التالي