إعادة التوجيه (rewrites)
تسمح لك إعادة التوجيه (rewrites) بتعيين مسار طلب وارد إلى مسار وجهة مختلف.
تعمل إعادة التوجيه كوكيل URL وتخفي مسار الوجهة، مما يجعل المستخدم يبدو وكأنه لم يغير موقعه على الموقع. على العكس من ذلك، فإن إعادة التوجيه (redirects) ستعيد توجيه إلى صفحة جديدة وتظهر تغييرات URL.
لاستخدام إعادة التوجيه، يمكنك استخدام مفتاح rewrites
في ملف next.config.js
:
module.exports = {
async rewrites() {
return [
{
source: '/about',
destination: '/',
},
]
},
}
يتم تطبيق إعادة التوجيه على التوجيه من جانب العميل، حيث سيتم تطبيق إعادة التوجيه على <Link href="/about">
في المثال أعلاه.
rewrites
هي دالة غير متزامنة تتوقع إرجاع مصفوفة أو كائن من المصفوفات (انظر أدناه) يحتوي على كائنات بخصائص source
و destination
:
source
:String
- هو نمط مسار الطلب الوارد.destination
:String
- المسار الذي تريد التوجيه إليه.basePath
:false
أوundefined
- إذا كانت القيمة false فلن يتم تضمين basePath عند المطابقة، يمكن استخدامها لإعادة التوجيه الخارجية فقط.locale
:false
أوundefined
- ما إذا كان يجب عدم تضمين اللغة المحلية عند المطابقة.has
هي مصفوفة من كائنات has بخصائصtype
وkey
وvalue
.missing
هي مصفوفة من كائنات missing بخصائصtype
وkey
وvalue
.
عندما ترجع دالة rewrites
مصفوفة، يتم تطبيق إعادة التوجيه بعد التحقق من نظام الملفات (الصفحات وملفات /public
) وقبل المسارات الديناميكية. عندما ترجع الدالة كائنًا من المصفوفات بشكل محدد، يمكن تغيير هذا السلوك والتحكم فيه بدقة أكبر، اعتبارًا من إصدار v10.1
من Next.js:
module.exports = {
async rewrites() {
return {
beforeFiles: [
// يتم التحقق من إعادة التوجيه هذه بعد الرؤوس/إعادة التوجيه
// وقبل جميع الملفات بما في ذلك ملفات _next/public مما
// يسمح بتجاوز ملفات الصفحات
{
source: '/some-page',
destination: '/somewhere-else',
has: [{ type: 'query', key: 'overrideMe' }],
},
],
afterFiles: [
// يتم التحقق من إعادة التوجيه هذه بعد التحقق من ملفات الصفحات/العامة
// ولكن قبل المسارات الديناميكية
{
source: '/non-existent',
destination: '/somewhere-else',
},
],
fallback: [
// يتم التحقق من إعادة التوجيه هذه بعد التحقق من ملفات الصفحات/العامة
// والمسارات الديناميكية
{
source: '/:path*',
destination: `https://my-old-site.com/:path*`,
},
],
}
},
}
معلومة مفيدة: إعادة التوجيه في
beforeFiles
لا تتحقق من نظام الملفات/المسارات الديناميكية مباشرة بعد مطابقة المصدر، بل تستمر حتى يتم التحقق من جميعbeforeFiles
.
ترتيب التحقق من المسارات في Next.js هو:
- يتم التحقق من الرؤوس وتطبيقها
- يتم التحقق من إعادة التوجيه وتطبيقها
- يتم التحقق من إعادة التوجيه
beforeFiles
وتطبيقها - يتم التحقق من الملفات الثابتة من الدليل العام، وملفات
_next/static
، والصفحات غير الديناميكية وتقديمها - يتم التحقق من إعادة التوجيه
afterFiles
وتطبيقها، إذا تمت مطابقة إحدى إعادة التوجيه هذه، نتحقق من المسارات الديناميكية/الملفات الثابتة بعد كل مطابقة - يتم التحقق من إعادة التوجيه
fallback
وتطبيقها، يتم تطبيق هذه قبل عرض صفحة 404 وبعد التحقق من جميع المسارات الديناميكية/الأصول الثابتة. إذا كنت تستخدم fallback: true/'blocking' فيgetStaticPaths
، فلن يتم تشغيل إعادة التوجيهfallback
المحددة في ملفnext.config.js
.
معلمات إعادة التوجيه
عند استخدام المعلمات في إعادة التوجيه، يتم تمرير المعلمات في الاستعلام افتراضيًا عندما لا يتم استخدام أي من المعلمات في destination
.
module.exports = {
async rewrites() {
return [
{
source: '/old-about/:path*',
destination: '/about', // لا يتم استخدام معلمة :path هنا لذا سيتم تمريرها تلقائيًا في الاستعلام
},
]
},
}
إذا تم استخدام معلمة في الوجهة، فلن يتم تمرير أي من المعلمات تلقائيًا في الاستعلام.
module.exports = {
async rewrites() {
return [
{
source: '/docs/:path*',
destination: '/:path*', // يتم استخدام معلمة :path هنا لذا لن يتم تمريرها تلقائيًا في الاستعلام
},
]
},
}
لا يزال بإمكانك تمرير المعلمات يدويًا في الاستعلام إذا تم استخدام واحد بالفعل في الوجهة عن طريق تحديد الاستعلام في destination
.
module.exports = {
async rewrites() {
return [
{
source: '/:first/:second',
destination: '/:first?second=:second',
// نظرًا لأن المعلمة :first مستخدمة في الوجهة، لن تتم إضافة المعلمة :second
// تلقائيًا في الاستعلام على الرغم من أنه يمكننا إضافتها يدويًا
// كما هو موضح أعلاه
},
]
},
}
معلومة مفيدة: سيتم تحليل معلمات الصفحات الثابتة من التحسين الثابت التلقائي أو التجهيز المسبق من إعادة التوجيه على العميل بعد التميؤ وتوفيرها في الاستعلام.
مطابقة المسار
يُسمح بمطابقة المسار، على سبيل المثال /blog/:slug
ستطابق /blog/hello-world
(بدون مسارات متداخلة):
module.exports = {
async rewrites() {
return [
{
source: '/blog/:slug',
destination: '/news/:slug', // يمكن استخدام المعلمات المتطابقة في الوجهة
},
]
},
}
مطابقة مسار Wildcard
لمطابقة مسار wildcard، يمكنك استخدام *
بعد معلمة، على سبيل المثال /blog/:slug*
ستطابق /blog/a/b/c/d/hello-world
:
module.exports = {
async rewrites() {
return [
{
source: '/blog/:slug*',
destination: '/news/:slug*', // يمكن استخدام المعلمات المتطابقة في الوجهة
},
]
},
}
مطابقة مسار Regex
لمطابقة مسار regex، يمكنك لف regex بين قوسين بعد معلمة، على سبيل المثال /blog/:slug(\\d{1,})
ستطابق /blog/123
ولكن ليس /blog/abc
:
module.exports = {
async rewrites() {
return [
{
source: '/old-blog/:post(\\d{1,})',
destination: '/blog/:post', // يمكن استخدام المعلمات المتطابقة في الوجهة
},
]
},
}
يتم استخدام الأحرف التالية (
, )
, {
, }
, [
, ]
, |
, \
, ^
, .
, :
, *
, +
, -
, ?
, $
لمطابقة مسار regex، لذا عند استخدامها في source
كقيم غير خاصة، يجب تهريبها بإضافة \\
قبلها:
module.exports = {
async rewrites() {
return [
{
// هذا سيطابق `/english(default)/something` عند الطلب
source: '/english\\(default\\)/:slug',
destination: '/en-us/:slug',
},
]
},
}
مطابقة الرأس، الكوكي، والاستعلام
لمطابقة إعادة توجيه فقط عندما تتطابق قيم الرأس أو الكوكي أو الاستعلام مع حقل has
أو لا تتطابق مع حقل missing
، يمكن استخدام has
و missing
. يجب أن تتطابق كل من source
وجميع عناصر has
وألا تتطابق جميع عناصر missing
لتطبيق إعادة التوجيه.
يمكن أن تحتوي عناصر has
و missing
على الحقول التالية:
type
:String
- يجب أن يكون إماheader
أوcookie
أوhost
أوquery
.key
:String
- المفتاح من النوع المحدد للمطابقة ضده.value
:String
أوundefined
- القيمة للتحقق منها، إذا كانت undefined فستطابق أي قيمة. يمكن استخدام سلسلة تشبه regex لالتقاط جزء معين من القيمة، على سبيل المثال إذا تم استخدام القيمةfirst-(?<paramName>.*)
لـfirst-second
فسيتم استخدامsecond
في الوجهة مع:paramName
.
module.exports = {
async rewrites() {
return [
// إذا كان الرأس `x-rewrite-me` موجودًا،
// سيتم تطبيق إعادة التوجيه هذه
{
source: '/:path*',
has: [
{
type: 'header',
key: 'x-rewrite-me',
},
],
destination: '/another-page',
},
// إذا كان الرأس `x-rewrite-me` غير موجود،
// سيتم تطبيق إعادة التوجيه هذه
{
source: '/:path*',
missing: [
{
type: 'header',
key: 'x-rewrite-me',
},
],
destination: '/another-page',
},
// إذا تمت مطابقة المصدر والاستعلام والكوكي،
// سيتم تطبيق إعادة التوجيه هذه
{
source: '/specific/:path*',
has: [
{
type: 'query',
key: 'page',
// لن تكون قيمة الصفحة متاحة في
// الوجهة نظرًا لتوفير القيمة وعدم
// استخدام مجموعة التقاط مسماة مثل (?<page>home)
value: 'home',
},
{
type: 'cookie',
key: 'authorized',
value: 'true',
},
],
destination: '/:path*/home',
},
// إذا كان الرأس `x-authorized` موجودًا و
// يحتوي على قيمة مطابقة، سيتم تطبيق إعادة التوجيه هذه
{
source: '/:path*',
has: [
{
type: 'header',
key: 'x-authorized',
value: '(?<authorized>yes|true)',
},
],
destination: '/home?authorized=:authorized',
},
// إذا كان المضيف هو `example.com`،
// سيتم تطبيق إعادة التوجيه هذه
{
source: '/:path*',
has: [
{
type: 'host',
value: 'example.com',
},
],
destination: '/another-page',
},
]
},
}
إعادة التوجيه إلى URL خارجي
تسمح لك إعادة التوجيه بإعادة التوجيه إلى URL خارجي. هذا مفيد بشكل خاص للتبني التدريجي لـ Next.js. فيما يلي مثال لإعادة توجيه مسار /blog
من تطبيقك الرئيسي إلى موقع خارجي.
module.exports = {
async rewrites() {
return [
{
source: '/blog',
destination: 'https://example.com/blog',
},
{
source: '/blog/:slug',
destination: 'https://example.com/blog/:slug', // يمكن استخدام المعلمات المتطابقة في الوجهة
},
]
},
}
إذا كنت تستخدم trailingSlash: true
، فأنت بحاجة أيضًا إلى إضافة شرطة مائلة في نهاية المعلمة source
. إذا كان خادم الوجهة يتوقع أيضًا شرطة مائلة في النهاية، فيجب تضمينها في المعلمة destination
.
module.exports = {
trailingSlash: true,
async rewrites() {
return [
{
source: '/blog/',
destination: 'https://example.com/blog/',
},
{
source: '/blog/:path*/',
destination: 'https://example.com/blog/:path*/',
},
]
},
}
التبني التدريجي لـ Next.js
يمكنك أيضًا جعل Next.js يعود إلى الوكيل لموقع ويب موجود بعد التحقق من جميع مسارات Next.js.
بهذه الطريقة لا تحتاج إلى تغيير تكوين إعادة التوجيه عند نقل المزيد من الصفحات إلى Next.js
module.exports = {
async rewrites() {
return {
fallback: [
{
source: '/:path*',
destination: `https://custom-routes-proxying-endpoint.vercel.app/:path*`,
},
],
}
},
}
إعادة التوجيه مع دعم basePath
عند استخدام دعم basePath
مع إعادة التوجيه، يتم إضافة basePath
تلقائيًا إلى كل source
و destination
ما لم تضيف basePath: false
إلى إعادة التوجيه:
module.exports = {
basePath: '/docs',
async rewrites() {
return [
{
source: '/with-basePath', // يصبح تلقائيًا /docs/with-basePath
destination: '/another', // يصبح تلقائيًا /docs/another
},
{
// لا يضيف /docs إلى /without-basePath نظرًا لتعيين basePath: false
// ملاحظة: لا يمكن استخدام هذا لإعادة التوجيه الداخلية مثل `destination: '/another'`
source: '/without-basePath',
destination: 'https://example.com',
basePath: false,
},
]
},
}
إعادة التوجيه مع دعم i18n
عند استخدام دعم i18n
مع إعادة التوجيه، يتم إضافة البادئات تلقائيًا إلى source
و destination
للتعامل مع locales
المكونة ما لم تضيف locale: false
إلى إعادة التوجيه. إذا تم استخدام locale: false
، يجب إضافة بادئة اللغة إلى source
و destination
لمطابقتها بشكل صحيح.
module.exports = {
i18n: {
locales: ['en', 'fr', 'de'],
defaultLocale: 'en',
},
async rewrites() {
return [
{
source: '/with-locale', // يتعامل تلقائيًا مع جميع اللغات
destination: '/another', // يمرر اللغة تلقائيًا
},
{
// لا يتعامل مع اللغات تلقائيًا نظرًا لتعيين locale: false
source: '/nl/with-locale-manual',
destination: '/nl/another',
locale: false,
},
{
// هذا يطابق '/' لأن `en` هي defaultLocale
source: '/en',
destination: '/en/another',
locale: false,
},
{
// من الممكن مطابقة جميع اللغات حتى عند تعيين locale: false
source: '/:locale/api-alias/:path*',
destination: '/api/:path*',
locale: false,
},
{
// يتم تحويل هذا إلى /(en|fr|de)/(.*) لذا لن يطابق
// المسارات العلوية `/` أو `/fr` مثل /:path*
source: '/(.*)',
destination: '/another',
},
]
},
}
سجل الإصدارات
الإصدار | التغييرات |
---|---|
v13.3.0 | تم إضافة missing . |
v10.2.0 | تم إضافة has . |
v9.5.0 | تم إضافة العناوين. |