إعادة التوجيه (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.
لا يتم تطبيق إعادة التوجيهات على التوجيه من جانب العميل (Link، router.push)، إلا إذا كان البرنامج الوسيط موجودًا ويتطابق مع المسار.
عند تطبيق إعادة التوجيه، سيتم تمرير أي قيم استعلام مقدمة في الطلب إلى وجهة إعادة التوجيه. على سبيل المثال، انظر إلى تكوين إعادة التوجيه التالي:
{
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,
},
]
},
}مطابقة مسار النمط العام
لمطابقة مسار النمط العام، يمكنك استخدام * بعد معلمة، على سبيل المثال /blog/:slug* سيطابق /blog/a/b/c/d/hello-world:
module.exports = {
async redirects() {
return [
{
source: '/blog/:slug*',
destination: '/news/:slug*', // يمكن استخدام المعلمات المطابقة في الوجهة
permanent: true,
},
]
},
}مطابقة مسار التعبير النمطي
لمطابقة مسار تعبير نمطي، يمكنك لف التعبير النمطي بين قوسين بعد معلمة، على سبيل المثال /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,
},
]
},
}مطابقة الرأس، الكوكي، والاستعلام
لمطابقة إعادة التوجيه فقط عندما تتطابق قيم الرأس أو الكوكي أو الاستعلام مع حقل 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، يمكنك استخدام
res.redirect(). - داخل
getStaticPropsوgetServerSideProps، يمكنك إعادة توجيه صفحات محددة في وقت الطلب.
سجل الإصدارات
| الإصدار | التغييرات |
|---|---|
v13.3.0 | تمت إضافة missing. |
v10.2.0 | تمت إضافة has. |
v9.5.0 | تمت إضافة redirects. |