Middleware في Next.js عام 2026: حارسات المصادقة واختبارات A/B وما ينتمي إلى الحافة
جدول المحتويات
عن الكاتب

Ahmed Mahmoud
كاتب ومطوّر
مهندس برمجيات شغوف بتطوير الويب وتصميم تجربة المستخدم.
مؤسّس ديفيا · eng-ahmed.com ↗النقاط الرئيسية
تعترض Middleware في Next.js — المُعرَّفة في middleware.ts في جذر المشروع — كل طلب يطابق النمط قبل الكاش والعرض وتشغيل أي مسار. هذا الموضع يجعلها الطبقة الصحيحة لإعادة توجيه المصادقة وتحديد اللغة وتوزيع اختبارات A/B.
تستطيع Middleware قراءة الطلبات وإعادة كتابتها وضبط الكوكيز وإعادة التوجيه أو إرجاع استجابة مبكرة دون تشغيل المسار. استعلامات قاعدة البيانات والحزم الضخمة لا تنتمي إليها لأنها تُضيف زمن استجابة لكل طلب.
في عام 2026 على Vercel، تعمل Middleware على Fluid Compute أي Node.js القياسي، لا وقت تشغيل Edge القديم المقيد. القيد الحقيقي هو ميزانية زمن الاستجابة: كل ميلي ثانية مُضافة تُدفع مع كل طلب.
إعداد matcher يُحدد نطاق Middleware على المسارات المطلوبة فقط. بدونه تعمل على كل طلب بما في ذلك الملفات الثابتة مما يُضيف عبئاً غير مجدٍ.
المصادقة في Middleware تعني التحقق من JWT مكتفٍ ذاتياً دون استدعاء قاعدة البيانات. التحقق الكامل من الجلسة ينتمي إلى المسار أو مكوّن الخادم.
ما هي Middleware في Next.js وأين تقع في دورة حياة الطلب؟
Middleware في Next.js هي دالة يتم تصديرها من middleware.ts في جذر المشروع. تعترض كل طلب يطابق النمط قبل بحث Next.js عن المسار وقبل الكاش وقبل تشغيل أي مكوّن خادم أو Route Handler. تستقبل NextRequest وتُرجع NextResponse: مرور (next)، إعادة توجيه (redirect)، إعادة كتابة (rewrite — محتوى مختلف مع URL أصلي في شريط العنوان)، أو استجابة مباشرة توقف المسار كلياً.
بدون matcher تعمل على كل شيء بما في ذلك الملفات الثابتة. على Vercel في 2026 تعمل على Fluid Compute — Node.js القياسي — لذا لم تعد قيود Edge Runtime سارية. الهدف: أقل من 10 ميلي ثانية.
كيف نكتب حارساً للمصادقة في Middleware؟
يقرأ الحارس JWT من كوكي HttpOnly ويتحقق منه محلياً بمكتبة jose دون الاتصال بقاعدة البيانات، ويُعيد التوجيه لصفحة تسجيل الدخول إذا كان الرمز مفقوداً أو منتهي الصلاحية. يجب أن يكون JWT موقَّعاً ومكتفياً ذاتياً — معرّف الجلسة الغامض يستلزم استعلام قاعدة بيانات وهو بطيء لـ Middleware. هدف إعادة التوجيه يجب أن يكون كائن URL لا نصاً خاماً، واحذف الكوكي عند الفشل لمنع حلقة إعادة التوجيه.
كيف نُجري اختبارات A/B في Middleware؟
ثلاث خطوات: التحقق من كوكي تعيين مجموعة، تعيين مجموعة إن لم تُوجد، وإعادة كتابة الطلب إلى URL المتغير. إعادة الكتابة تُبقي URL الأصلي في شريط العنوان — روابط المشاركة دائماً تشير إلى مسار التحكم. يحتوي كل متغير في دليل مسبوق بـ underscore يُعامله Next.js كدليل خاص غير متاح للتصفح المباشر.
ماذا تستطيع Middleware قراءته وكتابته وإرجاعه؟
تستقبل NextRequest مع request.cookies وrequest.nextUrl وrequest.ip وrequest.geo وrequest.headers. نُمرر القيم المحلولة للمنبع عبر رؤوس مخصصة في NextResponse.next() — هكذا نُمرر اللغة ومعرّف المستخدم لمكوّنات الخادم دون إعادة احتساب في كل تخطيط. أنواع الإرجاع الأربعة: مرور، redirect (URL يتغير)، rewrite (URL يبقى)، استجابة مباشرة (المسار لا يعمل).
ما الذي يجب أن لا نضعه في Middleware؟
استعلامات قاعدة البيانات: كل طلب يدفع تكلفة الرحلة قبل المسار — استخدم JWT قابلاً للتحقق الذاتي بدلاً منها. الحزم الثقيلة: تزيد من وقت البداية الباردة — أبقِ الاستيرادات في حدودها الدنيا (jose وحسب). تحديد المعدل عبر Redis البعيد: مهلة Redis تصبح مهلة لكل طلب — ضع تحديد المعدل في Route Handler منفصل.
الأسئلة الشائعة
**س: هل تعمل Middleware على الملفات الثابتة؟** ج: فقط على المسارات المطابقة لـ config.matcher. بدونه تعمل على كل شيء بما في ذلك _next/static.
**س: هل يمكننا الاستعلام من قاعدة البيانات في Middleware؟** ج: تقنياً نعم لكن يجب تجنبه. كل طلب يدفع تكلفة الرحلة. استخدم JWT مكتفياً ذاتياً.
**س: ما الفرق بين redirect وrewrite؟** ج: redirect يُرسل 307/308 ويتغير URL في المتصفح. rewrite يُقدم محتوى مختلفاً مع إبقاء URL الأصلي. المصادقة → redirect؛ A/B → rewrite.
**س: هل يمكن لـ Middleware قراءة جسم POST؟** ج: لا — تخزينه يكسر البث ويمنع المسار من قراءته.
**س: هل Edge Runtime مطلوب لـ Middleware في 2026؟** ج: ليس على Vercel. تعمل الآن على Fluid Compute — Node.js القياسي.
قراءات إضافية
هندسة الواجهات
الوضع الداكن دون وميض في Next.js 16: كيف نستخدم سكربت سمة حاجبًا وcolor-scheme وزر تبديل آمنًا مع الـ Hydration
وميض الوضع الداكن عند إعادة تحميل الصفحة مشكلة توقيت: الخادم لا يستطيع قراءة localStorage. نشرح سكربت السمة الحاجب الذي نستخدمه في Next.js 16، ولماذا لا نضع السمة في cookie حفاظًا على الرسم الثابت، وكيف نبني زر تبديل يمر بالـ hydration دون أي عدم تطابق.
هندسة الواجهات
صور Open Graph الديناميكية في Next.js 16: كيف نبني opengraph-image.tsx ونتحقق من إصدار Satori الذي تضمّنه next/og ونحافظ على صحة معاينات الروابط
واجهت بطاقات المشاركة المولّدة لدينا ثلاث مفاجآت: خط WOFF2 لم يستطع المحرّك قراءته، وملف README لـ Satori يصف محرّكًا أحدث من المضمّن في Next.js، وصفحة ظلّت تعرض صورة الـ layout. هذه ملاحظاتنا الميدانية حول opengraph-image.tsx في Next.js 16 وأولوية البيانات الوصفية وفحص og:image قبل مشاركة أي رابط.