إعادة التوجيه (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
) وقبل المسارات الديناميكية. عندما ترجع دالة rewrites
كائنًا من المصفوفات بشكل محدد، يمكن تغيير هذا السلوك والتحكم فيه بدقة أكبر، اعتبارًا من 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 هو:
- يتم التحقق من الرؤوس (headers) وتطبيقها
- يتم التحقق من عمليات إعادة التوجيه (redirects) وتطبيقها
- يتم التحقق من عمليات إعادة التوجيه
beforeFiles
وتطبيقها - يتم التحقق من الملفات الثابتة من الدليل العام (public directory)، وملفات
_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
// تلقائيًا في الاستعلام على الرغم من أنه يمكننا إضافتها يدويًا
// كما هو موضح أعلاه
},
]
},
}
معلومة جيدة: سيتم تحليل معلمات الصفحات الثابتة من التحسين الثابت التلقائي (Automatic Static Optimization) أو التقديم المسبق (prerendering) من عمليات إعادة التوجيه على العميل بعد الترطيب وتوفيرها في الاستعلام.
مطابقة المسار
يُسمح بمطابقة المسار، على سبيل المثال /blog/:slug
سيطابق /blog/hello-world
(بدون مسارات متداخلة):
module.exports = {
async rewrites() {
return [
{
source: '/blog/:slug',
destination: '/news/:slug', // يمكن استخدام المعلمات المطابقة في الوجهة
},
]
},
}
مطابقة مسار البدل
لمطابقة مسار بدل، يمكنك استخدام *
بعد معلمة، على سبيل المثال /blog/:slug*
سيطابق /blog/a/b/c/d/hello-world
:
module.exports = {
async rewrites() {
return [
{
source: '/blog/:slug*',
destination: '/news/:slug*', // يمكن استخدام المعلمات المطابقة في الوجهة
},
]
},
}
مطابقة مسار التعبير العادي (Regex)
لمطابقة مسار تعبير عادي، يمكنك لف التعبير بين قوسين بعد معلمة، على سبيل المثال /blog/:slug(\\d{1,})
سيطابق /blog/123
ولكن ليس /blog/abc
:
module.exports = {
async rewrites() {
return [
{
source: '/old-blog/:post(\\d{1,})',
destination: '/blog/:post', // يمكن استخدام المعلمات المطابقة في الوجهة
},
]
},
}
يتم استخدام الأحرف التالية (
, )
, {
, }
, [
, ]
, |
, \
, ^
, .
, :
, *
, +
, -
, ?
, $
لمطابقة مسار التعبير العادي، لذا عند استخدامها في 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 فستطابق أي قيمة. يمكن استخدام سلسلة تشبه التعبير العادي لالتقاط جزء محدد من القيمة، على سبيل المثال إذا تم استخدام القيمة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,
},
]
},
}
سجل الإصدارات
الإصدار | التغييرات |
---|---|
v13.3.0 | تمت إضافة missing . |
v10.2.0 | تمت إضافة has . |
v9.5.0 | تمت إضافة الرؤوس. |