إعادة التوجيه (redirects)
تسمح لك إعادة التوجيه (redirects) بتوجيه مسار طلب وارد إلى مسار وجهة مختلف.
لاستخدام إعادة التوجيه، يمكنك استخدام مفتاح redirects
في ملف 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
}
عند طلب /old-blog/post-1?hello=world
، سيتم توجيه العميل إلى /blog/post-1?hello=world
.
مطابقة المسار
يُسمح بمطابقة المسار، على سبيل المثال /old-blog/:slug
ستطابق /old-blog/hello-world
(بدون مسارات متداخلة):
module.exports = {
async redirects() {
return [
{
source: '/old-blog/:slug',
destination: '/news/:slug', // يمكن استخدام المعلمات المتطابقة في الوجهة
permanent: true,
},
]
},
}
مطابقة المسار باستخدام الأحرف البدل (Wildcard)
لمطابقة مسار باستخدام الأحرف البدل، يمكنك استخدام *
بعد المعلمة، على سبيل المثال /blog/:slug*
ستطابق /blog/a/b/c/d/hello-world
:
module.exports = {
async redirects() {
return [
{
source: '/blog/:slug*',
destination: '/news/:slug*', // يمكن استخدام المعلمات المتطابقة في الوجهة
permanent: true,
},
]
},
}
مطابقة المسار باستخدام التعبير النمطي (Regex)
لمطابقة مسار باستخدام التعبير النمطي، يمكنك تغليف التعبير النمطي بين قوسين بعد المعلمة، على سبيل المثال /post/:slug(\\d{1,})
ستطابق /post/123
ولكن لن تطابق /post/abc
:
module.exports = {
async redirects() {
return [
{
source: '/post/:slug(\\d{1,})',
destination: '/news/:slug', // يمكن استخدام المعلمات المتطابقة في الوجهة
permanent: false,
},
]
},
}
يتم استخدام الأحرف التالية (
, )
, {
, }
, :
, *
, +
, ?
لمطابقة مسار التعبير النمطي، لذا عند استخدامها في source
كقيم غير خاصة، يجب الهروب منها بإضافة \\
قبلها:
module.exports = {
async redirects() {
return [
{
// هذا سيطابق `/english(default)/something` عند الطلب
source: '/english\\(default\\)/:slug',
destination: '/en-us/:slug',
permanent: false,
},
]
},
}
مطابقة الرأس (Header)، الكوكي (Cookie)، والاستعلام (Query)
لمطابقة إعادة التوجيه فقط عندما تتطابق قيم الرأس أو الكوكي أو الاستعلام مع حقل has
أو لا تتطابق مع حقل missing
، يمكن استخدام 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
.
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
إلى إعادة التوجيه:
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
لمطابقتها بشكل صحيح.
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,
},
]
},
}
في بعض الحالات النادرة، قد تحتاج إلى تعيين رمز حالة مخصص لعملاء HTTP القديمة لإعادة التوجيه بشكل صحيح. في هذه الحالات، يمكنك استخدام خاصية statusCode
بدلاً من خاصية permanent
، ولكن ليس كلاهما. لضمان توافق IE11، يتم إضافة رأس Refresh
تلقائيًا لرمز الحالة 308.
إعادة التوجيه الأخرى
- داخل مسارات API و معالجات المسار (Route Handlers)، يمكنك إعادة التوجيه بناءً على الطلب الوارد.
- داخل
getStaticProps
وgetServerSideProps
، يمكنك إعادة توجيه صفحات محددة في وقت الطلب.
سجل الإصدارات
الإصدار | التغييرات |
---|---|
v13.3.0 | تمت إضافة missing . |
v10.2.0 | تمت إضافة has . |
v9.5.0 | تمت إضافة redirects . |