إعادة التوجيه (redirects)

تسمح لك إعادة التوجيه (redirects) بتوجيه مسار طلب وارد إلى مسار وجهة مختلف.

لاستخدام إعادة التوجيه، يمكنك استخدام مفتاح redirects في ملف next.config.js:

next.config.js
module.exports = {
  async redirects() {
    return [
      {
        source: '/about',
        destination: '/',
        permanent: true,
      },
    ]
  },
}

redirects هي دالة غير متزامنة تتوقع إرجاع مصفوفة تحتوي على كائنات ذات خصائص source و destination و permanent:

  • source: نمط مسار الطلب الوارد.
  • destination: المسار الذي تريد توجيه الطلب إليه.
  • permanent: true أو false - إذا كانت true سيتم استخدام رمز الحالة 308 الذي يوجه العملاء ومحركات البحث إلى تخزين إعادة التوجيه مؤقتًا، إذا كانت false سيتم استخدام رمز الحالة 307 المؤقت والذي لا يتم تخزينه.

لماذا يستخدم Next.js الرموز 307 و 308؟ تقليديًا، كان يتم استخدام 302 لإعادة التوجيه المؤقتة و301 لإعادة التوجيه الدائمة، لكن العديد من المتصفحات غيرت طريقة طلب إعادة التوجيه إلى GET بغض النظر عن الطريقة الأصلية. على سبيل المثال، إذا قام المتصفح بطلب POST /v1/users الذي أعاد رمز الحالة 302 مع موقع /v2/users، فقد يكون الطلب اللاحق GET /v2/users بدلاً من POST /v2/users المتوقع. يستخدم Next.js رمز الحالة 307 لإعادة التوجيه المؤقتة و308 لإعادة التوجيه الدائمة للحفاظ بشكل صريح على طريقة الطلب المستخدمة.

  • basePath: false أو undefined - إذا كانت false فلن يتم تضمين basePath عند التطابق، يمكن استخدامها لإعادة التوجيه الخارجية فقط.
  • locale: false أو undefined - ما إذا كان يجب عدم تضمين اللغة المحلية عند التطابق.
  • has: مصفوفة من كائنات has مع خصائص type و key و value.
  • missing: مصفوفة من كائنات missing مع خصائص type و key و value.

يتم التحقق من إعادة التوجيه قبل نظام الملفات الذي يتضمن الصفحات وملفات /public.

عند استخدام موجه الصفحات (Pages Router)، لا يتم تطبيق إعادة التوجيه على التوجيه من جانب العميل (Link، router.push) إلا إذا كان البرنامج الوسيط (Middleware) موجودًا ويتطابق مع المسار.

عند تطبيق إعادة التوجيه، سيتم تمرير أي قيم استعلام مقدمة في الطلب إلى وجهة إعادة التوجيه. على سبيل المثال، انظر إلى تكوين إعادة التوجيه التالي:

{
  source: '/old-blog/:path*',
  destination: '/blog/:path*',
  permanent: false
}

من الجيد معرفة: تذكر تضمين الشرطة المائلة / قبل النقطتين : في معلمات المسار لـ source و destination، وإذا لم يتم ذلك، فسيتم التعامل مع المسار كسلسلة حرفية وقد يؤدي ذلك إلى إعادة توجيه لا نهائية.

عند طلب /old-blog/post-1?hello=world، سيتم توجيه العميل إلى /blog/post-1?hello=world.

مطابقة المسار

يُسمح بمطابقة المسار، على سبيل المثال /old-blog/:slug سيطابق /old-blog/hello-world (بدون مسارات متداخلة):

next.config.js
module.exports = {
  async redirects() {
    return [
      {
        source: '/old-blog/:slug',
        destination: '/news/:slug', // يمكن استخدام المعلمات المتطابقة في الوجهة
        permanent: true,
      },
    ]
  },
}

مطابقة المسار باستخدام الحرف العام

لمطابقة مسار باستخدام حرف عام، يمكنك استخدام * بعد معلمة، على سبيل المثال /blog/:slug* سيطابق /blog/a/b/c/d/hello-world:

next.config.js
module.exports = {
  async redirects() {
    return [
      {
        source: '/blog/:slug*',
        destination: '/news/:slug*', // يمكن استخدام المعلمات المتطابقة في الوجهة
        permanent: true,
      },
    ]
  },
}

مطابقة المسار باستخدام التعبير النمطي

لمطابقة مسار باستخدام تعبير نمطي، يمكنك تغليف التعبير النمطي بين قوسين بعد معلمة، على سبيل المثال /post/:slug(\\d{1,}) سيطابق /post/123 ولكن ليس /post/abc:

next.config.js
module.exports = {
  async redirects() {
    return [
      {
        source: '/post/:slug(\\d{1,})',
        destination: '/news/:slug', // يمكن استخدام المعلمات المتطابقة في الوجهة
        permanent: false,
      },
    ]
  },
}

الأحرف التالية (، )، {، }، :، *، +، ? تستخدم لمطابقة المسار باستخدام التعبير النمطي، لذلك عند استخدامها في source كقيم غير خاصة، يجب تهريبها بإضافة \\ قبلها:

next.config.js
module.exports = {
  async redirects() {
    return [
      {
        // هذا سيطابق طلب `/english(default)/something`
        source: '/english\\(default\\)/:slug',
        destination: '/en-us/:slug',
        permanent: false,
      },
    ]
  },
}

مطابقة الرأس، الكوكي، والاستعلام

لتطابق إعادة التوجيه فقط عندما تتطابق قيم الرأس أو الكوكي أو الاستعلام مع حقل has أو لا تتطابق مع حقل missing، يمكن استخدام هذه الحقول. يجب أن يتطابق كل من source وجميع عناصر has وألا تتطابق جميع عناصر missing لتطبيق إعادة التوجيه.

يمكن أن تحتوي عناصر has و missing على الحقول التالية:

  • type: String - يجب أن يكون إما header أو cookie أو host أو query.
  • key: String - المفتاح من النوع المحدد للمطابقة.
  • value: String أو undefined - القيمة للتحقق منها، إذا كانت undefined فإن أي قيمة ستطابق. يمكن استخدام سلسلة تشبه التعبير النمطي لالتقاط جزء معين من القيمة، على سبيل المثال إذا تم استخدام القيمة first-(?<paramName>.*) لـ first-second فإن second سيكون قابلاً للاستخدام في الوجهة مع :paramName.
next.config.js
module.exports = {
  async redirects() {
    return [
      // إذا كان رأس `x-redirect-me` موجودًا،
      // سيتم تطبيق إعادة التوجيه هذه
      {
        source: '/:path((?!another-page$).*)',
        has: [
          {
            type: 'header',
            key: 'x-redirect-me',
          },
        ],
        permanent: false,
        destination: '/another-page',
      },
      // إذا كان رأس `x-dont-redirect` موجودًا،
      // لن يتم تطبيق إعادة التوجيه هذه
      {
        source: '/:path((?!another-page$).*)',
        missing: [
          {
            type: 'header',
            key: 'x-do-not-redirect',
          },
        ],
        permanent: false,
        destination: '/another-page',
      },
      // إذا تم تطابق المصدر والاستعلام والكوكي،
      // سيتم تطبيق إعادة التوجيه هذه
      {
        source: '/specific/:path*',
        has: [
          {
            type: 'query',
            key: 'page',
            // لن تكون قيمة الصفحة متاحة في الوجهة
            // لأن القيمة مقدمة ولا تستخدم مجموعة التقاط مسماة مثل (?<page>home)
            value: 'home',
          },
          {
            type: 'cookie',
            key: 'authorized',
            value: 'true',
          },
        ],
        permanent: false,
        destination: '/another/:path*',
      },
      // إذا كان رأس `x-authorized` موجودًا ويحتوي على قيمة مطابقة،
      // سيتم تطبيق إعادة التوجيه هذه
      {
        source: '/',
        has: [
          {
            type: 'header',
            key: 'x-authorized',
            value: '(?<authorized>yes|true)',
          },
        ],
        permanent: false,
        destination: '/home?authorized=:authorized',
      },
      // إذا كان المضيف هو `example.com`،
      // سيتم تطبيق إعادة التوجيه هذه
      {
        source: '/:path((?!another-page$).*)',
        has: [
          {
            type: 'host',
            value: 'example.com',
          },
        ],
        permanent: false,
        destination: '/another-page',
      },
    ]
  },
}

إعادة التوجيه مع دعم basePath

عند الاستفادة من دعم basePath مع إعادة التوجيه، يتم إضافة basePath تلقائيًا إلى كل source و destination ما لم تقم بإضافة basePath: false إلى إعادة التوجيه:

next.config.js
module.exports = {
  basePath: '/docs',

  async redirects() {
    return [
      {
        source: '/with-basePath', // يصبح تلقائيًا /docs/with-basePath
        destination: '/another', // يصبح تلقائيًا /docs/another
        permanent: false,
      },
      {
        // لا يضيف /docs لأن basePath: false مضبوط
        source: '/without-basePath',
        destination: 'https://example.com',
        basePath: false,
        permanent: false,
      },
    ]
  },
}

إعادة التوجيه مع دعم i18n

عند الاستفادة من دعم i18n مع إعادة التوجيه، يتم إضافة البادئات تلقائيًا إلى كل source و destination للتعامل مع locales المكونة ما لم تقم بإضافة locale: false إلى إعادة التوجيه. إذا تم استخدام locale: false، يجب إضافة بادئة اللغة إلى source و destination لمطابقتها بشكل صحيح.

next.config.js
module.exports = {
  i18n: {
    locales: ['en', 'fr', 'de'],
    defaultLocale: 'en',
  },

  async redirects() {
    return [
      {
        source: '/with-locale', // يتعامل تلقائيًا مع جميع اللغات
        destination: '/another', // يمرر اللغة تلقائيًا
        permanent: false,
      },
      {
        // لا يتعامل مع اللغات تلقائيًا لأن locale: false مضبوط
        source: '/nl/with-locale-manual',
        destination: '/nl/another',
        locale: false,
        permanent: false,
      },
      {
        // هذا يطابق '/' لأن `en` هي defaultLocale
        source: '/en',
        destination: '/en/another',
        locale: false,
        permanent: false,
      },
      // من الممكن مطابقة جميع اللغات حتى عند ضبط locale: false
      {
        source: '/:locale/page',
        destination: '/en/newpage',
        permanent: false,
        locale: false,
      },
      {
        // هذا يتحول إلى /(en|fr|de)/(.*) لذلك لن يطابق المسارات
        // الأساسية `/` أو `/fr` مثل /:path* 
        source: '/(.*)',
        destination: '/another',
        permanent: false,
      },
    ]
  },
}

في بعض الحالات النادرة، قد تحتاج إلى تعيين رمز حالة مخصص لجعل المتصفحات القديمة تعيد التوجيه بشكل صحيح. في هذه الحالات، يمكنك استخدام خاصية statusCode بدلاً من خاصية permanent، ولكن ليس الاثنين معًا. لضمان التوافق مع IE11، يتم إضافة رأس Refresh تلقائيًا لرمز الحالة 308.

إعادة التوجيه الأخرى

سجل الإصدارات

الإصدارالتغييرات
v13.3.0تمت إضافة missing.
v10.2.0تمت إضافة has.
v9.5.0تمت إضافة redirects.