العربية

اكتشف برنامج Next.js الوسيط، وهي ميزة قوية لاعتراض الطلبات الواردة وتعديلها. تعلم كيفية تنفيذ المصادقة والترخيص وإعادة التوجيه واختبارات A/B بأمثلة عملية.

برنامج Next.js الوسيط: إتقان اعتراض الطلبات للتطبيقات الديناميكية

يوفر برنامج Next.js الوسيط (middleware) طريقة مرنة وقوية لاعتراض وتعديل الطلبات الواردة قبل أن تصل إلى مساراتك. تمكّنك هذه القدرة من تنفيذ مجموعة واسعة من الميزات، بدءًا من المصادقة والترخيص إلى إعادة التوجيه واختبارات A/B، كل ذلك مع تحسين الأداء. سيرشدك هذا الدليل الشامل عبر المفاهيم الأساسية لبرنامج Next.js الوسيط ويوضح كيفية استغلاله بفعالية.

ما هو برنامج Next.js الوسيط؟

البرنامج الوسيط في Next.js هو دالة تعمل قبل اكتمال الطلب. يسمح لك بما يلي:

يتم تعريف دوال البرنامج الوسيط في ملف middleware.ts (أو middleware.js) في جذر مشروعك. يتم تنفيذها لكل مسار داخل تطبيقك، أو لمسارات محددة بناءً على مطابقات (matchers) قابلة للتكوين.

المفاهيم والفوائد الرئيسية

كائن الطلب (Request Object)

يوفر كائن request الوصول إلى معلومات حول الطلب الوارد، بما في ذلك:

كائن الاستجابة (Response Object)

تُرجع دوال البرنامج الوسيط كائن Response للتحكم في نتيجة الطلب. يمكنك استخدام الاستجابات التالية:

المطابقات (Matchers)

تسمح لك المطابقات بتحديد المسارات التي يجب تطبيق برنامجك الوسيط عليها. يمكنك تحديد المطابقات باستخدام التعبيرات النمطية أو أنماط المسار. هذا يضمن أن برنامجك الوسيط يعمل فقط عند الضرورة، مما يحسن الأداء ويقلل من العبء الزائد.

وقت تشغيل الحافة (Edge Runtime)

يعمل برنامج Next.js الوسيط على وقت تشغيل الحافة (Edge Runtime)، وهو بيئة تشغيل JavaScript خفيفة الوزن يمكن نشرها بالقرب من المستخدمين. يقلل هذا القرب من زمن الوصول ويحسن الأداء العام لتطبيقك، خاصة للمستخدمين الموزعين عالميًا. يتوفر وقت تشغيل الحافة على شبكة Vercel's Edge ومنصات أخرى متوافقة. يحتوي وقت تشغيل الحافة على بعض القيود، وتحديدًا استخدام واجهات برمجة تطبيقات Node.js.

أمثلة عملية: تنفيذ ميزات البرنامج الوسيط

1. المصادقة (Authentication)

يمكن استخدام برنامج المصادقة الوسيط لحماية المسارات التي تتطلب من المستخدمين تسجيل الدخول. إليك مثال على كيفية تنفيذ المصادقة باستخدام ملفات تعريف الارتباط:


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
 const token = request.cookies.get('auth_token');

 if (!token) {
 return NextResponse.redirect(new URL('/login', request.url))
 }

 return NextResponse.next()
}

export const config = {
 matcher: ['/dashboard/:path*'],
}

يتحقق هذا البرنامج الوسيط من وجود ملف تعريف ارتباط auth_token. إذا لم يتم العثور على ملف تعريف الارتباط، يتم إعادة توجيه المستخدم إلى صفحة /login. يحدد config.matcher أن هذا البرنامج الوسيط يجب أن يعمل فقط للمسارات تحت /dashboard.

منظور عالمي: قم بتكييف منطق المصادقة لدعم طرق المصادقة المختلفة (مثل OAuth، JWT) والتكامل مع مزودي الهوية المختلفين (مثل Google، Facebook، Azure AD) لتلبية احتياجات المستخدمين من مناطق متنوعة.

2. الترخيص (Authorization)

يمكن استخدام برنامج الترخيص الوسيط للتحكم في الوصول إلى الموارد بناءً على أدوار المستخدمين أو أذوناتهم. على سبيل المثال، قد يكون لديك لوحة تحكم للمسؤول لا يمكن الوصول إليها إلا لمستخدمين محددين.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export async function middleware(request: NextRequest) {
 const token = request.cookies.get('auth_token');

 if (!token) {
 return NextResponse.redirect(new URL('/login', request.url))
 }

 // مثال: جلب أدوار المستخدم من واجهة برمجة تطبيقات (استبدل بالمنطق الفعلي الخاص بك)
 const userResponse = await fetch('https://api.example.com/userinfo', {
 headers: {
 Authorization: `Bearer ${token}`,
 },
 });
 const userData = await userResponse.json();

 if (userData.role !== 'admin') {
 return NextResponse.redirect(new URL('/unauthorized', request.url))
 }

 return NextResponse.next()
}

export const config = {
 matcher: ['/admin/:path*'],
}

يسترد هذا البرنامج الوسيط دور المستخدم ويتحقق مما إذا كان لديه دور admin. إذا لم يكن كذلك، يتم إعادة توجيههم إلى صفحة /unauthorized. يستخدم هذا المثال نقطة نهاية API وهمية. استبدل `https://api.example.com/userinfo` بنقطة نهاية خادم المصادقة الفعلي الخاص بك.

منظور عالمي: كن على دراية بلوائح خصوصية البيانات (مثل GDPR، CCPA) عند التعامل مع بيانات المستخدم. طبق الإجراءات الأمنية المناسبة لحماية المعلومات الحساسة وضمان الامتثال للقوانين المحلية.

3. إعادة التوجيه (Redirection)

يمكن استخدام برنامج إعادة التوجيه الوسيط لإعادة توجيه المستخدمين بناءً على موقعهم أو لغتهم أو معايير أخرى. على سبيل المثال، قد تعيد توجيه المستخدمين إلى نسخة مترجمة من موقعك على الويب بناءً على عنوان IP الخاص بهم.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
 const country = request.geo?.country || 'US'; // الافتراضي هو US إذا فشل تحديد الموقع الجغرافي

 if (country === 'DE') {
 return NextResponse.redirect(new URL('/de', request.url))
 }

 if (country === 'FR') {
 return NextResponse.redirect(new URL('/fr', request.url))
 }

 return NextResponse.next()
}

export const config = {
 matcher: ['/'],
}

يتحقق هذا البرنامج الوسيط من بلد المستخدم بناءً على عنوان IP الخاص به ويعيد توجيههم إلى النسخة المترجمة المناسبة من الموقع (/de لألمانيا، /fr لفرنسا). إذا فشل تحديد الموقع الجغرافي، فإنه ينتقل افتراضيًا إلى النسخة الأمريكية. لاحظ أن هذا يعتمد على توفر خاصية geo (على سبيل المثال، عند النشر على Vercel).

منظور عالمي: تأكد من أن موقعك يدعم لغات وعملات متعددة. امنح المستخدمين خيار تحديد لغتهم أو منطقتهم المفضلة يدويًا. استخدم تنسيقات التاريخ والوقت المناسبة لكل منطقة.

4. اختبار A/B

يمكن استخدام البرنامج الوسيط لتنفيذ اختبار A/B عن طريق تعيين المستخدمين عشوائيًا لمتغيرات مختلفة من الصفحة وتتبع سلوكهم. إليك مثال مبسط:


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

function getRandomVariant() {
 return Math.random() < 0.5 ? 'A' : 'B';
}

export function middleware(request: NextRequest) {
 let variant = request.cookies.get('variant')?.value;

 if (!variant) {
 variant = getRandomVariant();
 const response = NextResponse.next();
 response.cookies.set('variant', variant);
 return response;
 }

 if (variant === 'B') {
 return NextResponse.rewrite(new URL('/variant-b', request.url));
 }

 return NextResponse.next();
}

export const config = {
 matcher: ['/'],
}

يعين هذا البرنامج الوسيط المستخدمين إما للمتغير 'A' أو 'B'. إذا لم يكن لدى المستخدم بالفعل ملف تعريف ارتباط variant، يتم تعيين واحد عشوائيًا. يتم إعادة كتابة المستخدمين المعينين للمتغير 'B' إلى صفحة /variant-b. ستقوم بعد ذلك بتتبع أداء كل متغير لتحديد أيهما أكثر فعالية.

منظور عالمي: ضع في اعتبارك الاختلافات الثقافية عند تصميم اختبارات A/B. ما يعمل بشكل جيد في منطقة ما قد لا يلقى صدى لدى المستخدمين في منطقة أخرى. تأكد من أن منصة اختبار A/B الخاصة بك متوافقة مع لوائح الخصوصية في المناطق المختلفة.

5. أعلام الميزات (Feature Flags)

تسمح لك أعلام الميزات بتمكين أو تعطيل الميزات في تطبيقك دون نشر كود جديد. يمكن استخدام البرنامج الوسيط لتحديد ما إذا كان يجب أن يكون لدى المستخدم حق الوصول إلى ميزة معينة بناءً على معرف المستخدم الخاص به أو موقعه أو معايير أخرى.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export async function middleware(request: NextRequest) {
 // مثال: جلب أعلام الميزات من واجهة برمجة تطبيقات
 const featureFlagsResponse = await fetch('https://api.example.com/featureflags', {
 headers: {
 'X-User-Id': 'user123',
 },
 });
 const featureFlags = await featureFlagsResponse.json();

 if (featureFlags.new_feature_enabled) {
 // تمكين الميزة الجديدة
 return NextResponse.next();
 } else {
 // تعطيل الميزة الجديدة (على سبيل المثال، إعادة التوجيه إلى صفحة بديلة)
 return NextResponse.redirect(new URL('/alternative-page', request.url));
 }
}

export const config = {
 matcher: ['/new-feature'],
}

يجلب هذا البرنامج الوسيط أعلام الميزات من واجهة برمجة تطبيقات ويتحقق مما إذا كان علم new_feature_enabled معينًا. إذا كان الأمر كذلك، يمكن للمستخدم الوصول إلى صفحة /new-feature. وإلا، يتم إعادة توجيههم إلى صفحة /alternative-page.

منظور عالمي: استخدم أعلام الميزات لإطلاق الميزات الجديدة تدريجيًا للمستخدمين في مناطق مختلفة. يتيح لك ذلك مراقبة الأداء ومعالجة أي مشكلات قبل إصدار الميزة لجمهور أوسع. أيضًا، تأكد من أن نظام أعلام الميزات الخاص بك يتوسع عالميًا ويوفر نتائج متسقة بغض النظر عن موقع المستخدم. ضع في اعتبارك القيود التنظيمية الإقليمية لإطلاق الميزات.

تقنيات متقدمة

سلسلة البرامج الوسيطة (Chaining Middleware)

يمكنك ربط عدة دوال برامج وسيطة معًا لتنفيذ سلسلة من العمليات على طلب واحد. يمكن أن يكون هذا مفيدًا لتقسيم المنطق المعقد إلى وحدات أصغر وأكثر قابلية للإدارة.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
 const response = NextResponse.next();

 // دالة البرنامج الوسيط الأولى
 const token = request.cookies.get('auth_token');
 if (!token) {
 return NextResponse.redirect(new URL('/login', request.url))
 }

 // دالة البرنامج الوسيط الثانية
 response.headers.set('x-middleware-custom', 'value');

 return response;
}

export const config = {
 matcher: ['/dashboard/:path*'],
}

يُظهر هذا المثال برنامجين وسيطين في واحد. الأول يقوم بالمصادقة والثاني يقوم بتعيين ترويسة مخصصة.

استخدام متغيرات البيئة

قم بتخزين المعلومات الحساسة، مثل مفاتيح API وبيانات اعتماد قاعدة البيانات، في متغيرات البيئة بدلاً من كتابتها مباشرة في دوال البرنامج الوسيط. هذا يحسن الأمان ويسهل إدارة تكوين تطبيقك.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

const API_KEY = process.env.API_KEY;

export async function middleware(request: NextRequest) {
 const response = await fetch('https://api.example.com/data', {
 headers: {
 'X-API-Key': API_KEY,
 },
 });

 // ...
}

export const config = {
 matcher: ['/data'],
}

في هذا المثال، يتم استرداد API_KEY من متغير بيئة.

معالجة الأخطاء

نفّذ معالجة قوية للأخطاء في دوال البرنامج الوسيط لمنع الأخطاء غير المتوقعة من تعطيل تطبيقك. استخدم كتل try...catch لالتقاط الاستثناءات وتسجيل الأخطاء بشكل مناسب.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export async function middleware(request: NextRequest) {
 try {
 const response = await fetch('https://api.example.com/data');
 // ...
 } catch (error) {
 console.error('Error fetching data:', error);
 return NextResponse.error(); // أو إعادة التوجيه إلى صفحة خطأ
 }
}

export const config = {
 matcher: ['/data'],
}

أفضل الممارسات

استكشاف الأخطاء الشائعة وإصلاحها

الخاتمة

يعد برنامج Next.js الوسيط أداة قوية لبناء تطبيقات ويب ديناميكية وشخصية. من خلال إتقان اعتراض الطلبات، يمكنك تنفيذ مجموعة واسعة من الميزات، من المصادقة والترخيص إلى إعادة التوجيه واختبارات A/B. باتباع أفضل الممارسات الموضحة في هذا الدليل، يمكنك الاستفادة من برنامج Next.js الوسيط لإنشاء تطبيقات عالية الأداء وآمنة وقابلة للتطوير تلبي احتياجات قاعدة المستخدمين العالمية الخاصة بك. اغتنم قوة البرنامج الوسيط لفتح إمكانيات جديدة في مشاريع Next.js الخاصة بك وتقديم تجارب مستخدم استثنائية.

برنامج Next.js الوسيط: إتقان اعتراض الطلبات للتطبيقات الديناميكية | MLOG