Next.js

حل خطأ proxy.ts في Next.js 16: Missing Expected Function Export

حل خطأ «Proxy is missing expected function export name» في Next.js 16: كل الأسباب التي جربناها على 16.4.5، والتصدير الصحيح، وإعداد next-intl.

بقلم Aniq-UI05 نوفمبر 202615 دقيقة قراءة
مشاركة:
حل خطأ proxy.ts في Next.js 16: Missing Expected Function Export
#Next.js 16#proxy.ts#Middleware#next-intl#Troubleshooting#App Router#i18n

يوقف Next.js 16 عملية البناء برسالة الخطأ «Proxy is missing expected function export name» عندما لا يصدّر ملف proxy.ts دالة اسمها proxy ولا دالة افتراضية (default export). والسبب المعتاد ملف أُعيدت تسميته من middleware.ts وما زال يحتوي على export function middleware. غيّر اسم هذه الدالة إلى proxy، أو اجعلها التصدير الافتراضي، فينجح البناء.

أعدنا إنتاج كل حالة في هذه الصفحة يوم 5 نوفمبر 2026 في تطبيق جديد فارغ يعمل بـ Next.js 16.4.5 وnext-intl 4.14.9 وTurbopack (أداة البناء الافتراضية في Next.js 16)، ونسخنا الرسائل كما ظهرت في الطرفية. ثم بنينا كل حل من جديد للتأكد من أنه يعمل.

تمت المراجعة في نوفمبر 2026.

ماذا تقول رسالة الخطأ بالضبط؟

هذه الرسالة كاملة كما يطبعها next build في Next.js 16.4.5. والعبارة التي يبحث عنها المطورون «expected function export name default or proxy function export» مأخوذة من سطرها الأول ومن آخر تلميح فيها.

▲ Next.js 16.4.5 (Turbopack)
  Creating an optimized production build ...

> Build error occurred
Error: Turbopack build failed with 1 error:
./proxy.ts
Error: Proxy is missing expected function export name
This function is what Next.js runs for every request handled by this proxy (previously called middleware).

Why this happens:
- You are migrating from `middleware` to `proxy`, but haven't updated the exported function.
- The file exists but doesn't export a function.
- The export is not a function (e.g., an object or constant).
- There's a syntax error preventing the export from being recognized.

To fix it:
- Ensure this file has either a default or "proxy" function export.

Learn more: https://nextjs.org/docs/messages/middleware-to-proxy

ولنفس الخطأ صيغتان أخريان، بحسب طريقة تشغيل التطبيق:

# next build --webpack, and next dev
Error: The file "./proxy.ts" must export a function, either as a default export or as a named "proxy" export.

# next start or next dev, when a request reaches a proxy that exports no function
⨯ [Error: The Proxy file "/proxy" must export a function named `proxy` or a default function.]

والمعنى في الثلاث واحد: فتح Next.js ملف proxy.ts ولم يجد فيه دالة يستطيع استدعاءها مع كل طلب.

ما سبب خطأ «Proxy is missing expected function export name»؟

يقرأ Next.js ما يصدّره proxy.ts وقت البناء، ويبحث عن دالة اسمها proxy أو عن تصدير افتراضي. أي شيء آخر يفشل. وهذه أكثر صورة شائعة، ملف غُيّر اسمه يدويًا:

// proxy.ts (renamed from middleware.ts, function not renamed)
import { NextResponse, type NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
  return NextResponse.next();
}

بنينا كل شكل من هذه الأشكال على Next.js 16.4.5. والعمود الثاني يبيّن ما حدث.

محتوى proxy.tsالنتيجة على 16.4.5
export function middleware()يفشل البناء: missing expected function export name
export const middleware = ...يفشل البناء: الخطأ نفسه
دالة باسم آخر، مثل export function handler()يفشل البناء: الخطأ نفسه
export const config = {...} وحدهيفشل البناء: الخطأ نفسه
ملف فارغيفشل البناء: الخطأ نفسه
export const middleware = createMiddleware(routing) (next-intl)يفشل البناء: الخطأ نفسه
export { default as middleware } from 'next-intl/middleware'يفشل البناء: الخطأ نفسه
export * from './other-file'يفشل البناء: الخطأ نفسه، حتى لو كان الملف الآخر يصدّر proxy
export { middleware as default } from './old-middleware'ينجح التجميع (compile)، ثم يفشل عند مرحلة «Collecting page data» برسالة «must export a function»
export default { ... } (كائن وليس دالة)ينجح البناء، ثم يعيد كل طلب الخطأ 500
export const config = { runtime: 'edge' }يفشل البناء بخطأ مختلف: Proxy does not support Edge runtime
middleware.ts وproxy.ts معًايفشل البناء: اكتُشف الملفان
proxy.ts في الجذر بينما التطبيق في src/appينجح البناء، لكن الـ proxy لا يعمل أبدًا

الأسطر الثلاثة الأخيرة ليست خطأ التصدير نفسه، لكنها تظهر أثناء الانتقال نفسه، لذلك نشرحها في الأسفل.

الحل 1: صدّر دالة اسمها proxy

غيّر اسم الدالة إلى proxy. هذا هو الشكل الذي تستخدمه وثائق Next.js، وينجح معه البناء:

// proxy.ts
import { NextResponse, type NextRequest } from 'next/server';

export function proxy(request: NextRequest) {
  return NextResponse.next();
}

export const config = {
  matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
};

يمكن أن تكون الدالة async، وتعمل أيضًا الدالة السهمية المسندة إلى export const proxy. بنينا الاثنتين:

// Pick one. Each of these also builds on Next.js 16.4.5.
export async function proxy(request: NextRequest) {
  return NextResponse.next();
}

// or
export const proxy = (request: NextRequest) => NextResponse.next();

دالة واحدة في كل ملف. تقول وثائق Next.js إن الملف يجب أن يصدّر دالة واحدة، وإن وجود أكثر من proxy في ملف واحد غير مدعوم.

الحل 2: استخدم التصدير الافتراضي

التصدير الافتراضي يعمل مهما كان اسم الدالة، وحتى الدالة السهمية المجهولة المصدّرة افتراضيًا ينجح معها البناء. ومع ذلك يوصي دليل الترقية في Next.js بتسميتها proxy، ليتطابق اسمها مع اسم الملف:

// proxy.ts
import { NextResponse, type NextRequest } from 'next/server';

export default function proxy(request: NextRequest) {
  return NextResponse.next();
}

انتبه لفخ واحد: التصدير الافتراضي يجب أن يكون دالة. في اختبارنا مرّ export default { matcher: ['/'] } من next build، ثم أعادت كل صفحة الخطأ 500 مع الرسالة «The Proxy file "/proxy" must export a function named `proxy` or a default function.». وبعض صيغ إعادة التصدير تفشل أيضًا. استورد الدالة أولًا ثم صدّرها:

// Fails at "Collecting page data" on Next.js 16.4.5
export { middleware as default } from './old-middleware';

// Builds: import first, then export
import { middleware } from './old-middleware';
export default middleware;

كيف أكتب proxy.ts مع next-intl؟

الدالة createMiddleware() في next-intl تعيد دالة، فصدّرها كتصدير افتراضي. هذا هو الإعداد الموجود في وثائق next-intl، والتي تذكر أيضًا أن proxy.ts كان اسمه middleware.ts حتى Next.js 16:

// src/i18n/routing.ts
import { defineRouting } from 'next-intl/routing';

export const routing = defineRouting({
  locales: ['en', 'ar'],
  defaultLocale: 'en',
});
// src/proxy.ts
import createMiddleware from 'next-intl/middleware';
import { routing } from './i18n/routing';

export default createMiddleware(routing);

export const config = {
  // Skip /api, /trpc, /_next, /_vercel and any path with a dot (files)
  matcher: '/((?!api|trpc|_next|_vercel|.*\\..*).*)',
};

الصيغة export const proxy = createMiddleware(routing); ينجح معها البناء أيضًا، وهي ما يكتبه codemod الخاص بـ Next.js عندما ينقل ملف next-intl. أما هذه الأشكال فتفشل، لأن الدالة ليست باسم proxy أو لأن Next.js لا يراها وقت البناء:

// src/proxy.ts: these three fail with "missing expected function export name"
export const middleware = createMiddleware(routing);
export { default as middleware } from 'next-intl/middleware';
export * from './intl-proxy';

لتشغيل فحص خاص بك قبل إعادة التوجيه حسب اللغة (تسجيل الدخول، أو ترويسة، أو إعادة توجيه)، اكتب دالة proxy واستدعِ معالج next-intl من داخلها:

// src/proxy.ts: your own check first, then next-intl
import createMiddleware from 'next-intl/middleware';
import { NextResponse, type NextRequest } from 'next/server';
import { routing } from './i18n/routing';

const handleI18nRouting = createMiddleware(routing);

export function proxy(request: NextRequest) {
  const isAccount = request.nextUrl.pathname.includes('/account');
  const hasSession = request.cookies.has('session');

  if (isAccount && !hasSession) {
    return NextResponse.redirect(new URL('/en/login', request.url));
  }

  return handleI18nRouting(request);
}

export const config = {
  matcher: '/((?!api|trpc|_next|_vercel|.*\\..*).*)',
};

بنينا هذا الملف، وشغّلناه بالأمر next start -p 3040، وأرسلنا ثلاثة طلبات. اختار الـ proxy اللغة ونفّذ فحص الحساب:

$ curl -s -o /dev/null -w '%{http_code} %{redirect_url}\n' http://localhost:3040/
307 http://localhost:3040/en
$ curl -s -o /dev/null -w '%{http_code} %{redirect_url}\n' -H 'Accept-Language: ar' http://localhost:3040/
307 http://localhost:3040/ar
$ curl -s -o /dev/null -w '%{http_code} %{redirect_url}\n' http://localhost:3040/en/account
307 http://localhost:3040/en/login

إعادة التوجيه هذه هي التي ترسل الزائر نفسه إلى صفحة بالإنجليزية أو بالعربية. هذه الصفحة الرئيسية لقالب المطعم من Aniq UI على /en وعلى /ar:

الصفحة الرئيسية لقالب المطعم من Aniq UI بالإنجليزية على /en، بالوضع الداكن، العنوان على اليسار وصورة برغر على اليمين

الصفحة الرئيسية نفسها بالعربية على /ar، من اليمين إلى اليسار، العنوان على اليمين والصورة على اليسار

بعد أن تُحمَّل الصفحات العربية، يجب أن ينقلب التخطيط أيضًا. وهذا عمل CSS وليس عمل الـ proxy: يشرح دليل RTL في Tailwind CSS ضبط dir والأدوات المنطقية والمتغيّر rtl:.

أين أضع proxy.ts: في الجذر أم في src/؟

بجانب مجلد app. تقول وثائق Next.js أن تنشئه في جذر المشروع، أو داخل src إن كنت تستخدمه، بحيث يكون في نفس مستوى app أو pages.

# Without a src folder        # With a src folder
my-app/                       my-app/
├── app/                      ├── src/
├── proxy.ts                  │   ├── app/
└── package.json              │   └── proxy.ts
                              └── package.json

الملف في المكان الخطأ لا يعطي أي رسالة خطأ. في اختبارنا، ملف proxy.ts في جذر مشروع تطبيقه في src/app نجح بناؤه ولم يعمل أبدًا. وملف proxy.ts داخل مجلد app تجاهله Next.js بالطريقة نفسها. والفحص السريع في نهاية مخرجات next build: عندما يجد Next.js الـ proxy تنتهي قائمة المسارات بهذا السطر:

Route (app)
┌ ○ /
└ ○ /_not-found
ƒ Proxy (Middleware)

إذا لم يظهر السطر ƒ Proxy (Middleware) فـ Next.js لم يجد الملف. وإذا غيّرت pageExtensions في next.config فاسم الملف يتبعها، مثل proxy.page.ts.

هل يسبب matcher في config هذا الخطأ؟

لا. config اختياري، والملف الذي لا يحتوي إلا على config يفشل لأنه بلا دالة، لا بسبب الـ matcher. الـ matcher يحدد المسارات التي يعمل عليها الـ proxy. ومن دونه يعمل الـ proxy على كل طلب، بما في ذلك _next/static والصور وملفات public/. والنمط السالب يستبعدها:

export const config = {
  matcher: [
    // Everything except API routes, static files, image optimization and metadata files
    '/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)',
  ],
};

يجب أن تكون قيم الـ matcher ثابتة، لأن Next.js يقرؤها وقت البناء. وتقول الوثائق إن القيمة المبنية من متغير يتم تجاهلها. ويجب أن يبدأ كل source بالرمز /.

كيف أنتقل من middleware.ts إلى proxy.ts؟

شغّل الـ codemod الرسمي من جذر المشروع. يغيّر اسم الملف واسم الدالة المصدّرة:

npx @next/codemod@canary middleware-to-proxy .

شغّلناه (الإصدار 16.5.0-canary.41) على middleware.ts في الجذر وعلى src/middleware.ts يستخدم next-intl. تغيّر اسم الملفين واسم الدالتين، ونجح بناء التطبيقين:

// middleware.ts -> proxy.ts
- export function middleware(request: NextRequest) {
+ export function proxy(request: NextRequest) {

// src/middleware.ts -> src/proxy.ts
- export const middleware = createMiddleware(routing);
+ export const proxy = createMiddleware(routing);

لا يعمل إلا على دالة اسمها middleware. عندما جرّبناه على middleware.ts دالته اسمها handler، ترك الملف كما هو، فغيّر في هذه الحالة اسم الملف واسم الدالة يدويًا. والأمر الأشمل npx @next/codemod@canary upgrade latest يتضمن أيضًا خطوة الانتقال من middleware إلى proxy.

أمران آخران أثناء الانتقال:

  • ما زال middleware.ts يعمل في 16.4.5 مع تحذير. يطبع البناء التحذير التالي ثم يشغّل الملف. خطّط لتغيير الاسم مع ذلك، لأن هذه التسمية أصبحت مهجورة (deprecated).
  • لا تُبقِ الملفين معًا. مع وجود middleware.ts وproxy.ts جنبًا إلى جنب يتوقف البناء.
⚠ The "middleware" file convention is deprecated. Please use "proxy" instead.
  To migrate automatically, run:
  npx @next/codemod@canary middleware-to-proxy .
  Learn more: https://nextjs.org/docs/messages/middleware-to-proxy
Error: Both middleware file "./middleware.ts" and proxy file "./proxy.ts" are detected. Please use "./proxy.ts" only. Learn more: https://nextjs.org/docs/messages/middleware-to-proxy

وتغيّرت أيضًا أسماء خيارات الإعداد التي كانت تحتوي على كلمة middleware. مثلًا أصبح skipMiddlewareUrlNormalize باسم skipProxyUrlNormalize:

// next.config.ts
import type { NextConfig } from 'next';

const nextConfig: NextConfig = {
  skipProxyUrlNormalize: true, // was skipMiddlewareUrlNormalize
};

export default nextConfig;

هل يمكن أن يستخدم proxy.ts بيئة Edge؟

لا. يقول دليل الترقية إلى Next.js 16 إن بيئة تشغيل الـ proxy هي nodejs ولا يمكن تغييرها، وإن التطبيقات التي تحتاج إلى بيئة Edge عليها أن تبقى على middleware حاليًا. إضافة export const config = { runtime: 'edge' } إلى proxy.ts أوقفت البناء عندنا بهذه الرسالة:

./proxy.ts:7:14
Error: Next.js can't recognize the exported `config` field in route. Proxy does not support Edge runtime.
> 7 | export const config = { runtime: 'edge' };

احذف سطر runtime. وإذا كنت تعتمد فعلًا على Edge، فأبقِ middleware.ts إلى أن ينشر Next.js تعليماته اللاحقة.

قائمة فحص في دقيقة واحدة

  1. اسم الملف proxy.ts (أو .js) وهو بجانب app: في الجذر أو داخل src/.
  2. يصدّر function proxy أو دالة افتراضية، ولم يبقَ فيه اسم middleware.
  3. مع next-intl يكون السطر export default createMiddleware(routing);.
  4. لا يوجد ملف middleware.ts بجانبه.
  5. في config قيمة matcher ثابتة ولا يوجد runtime.
  6. تنتهي مخرجات next build بالسطر ƒ Proxy (Middleware)، والطلب في next start لا يعيد 500.

الأسئلة الشائعة

لماذا يظهر خطأ «missing expected function export name» في proxy.ts بعد الترقية إلى Next.js 16؟

لأن اسم الملف تغيّر ولم يتغيّر اسم الدالة. لا يقبل Next.js 16 في proxy.ts إلا دالة اسمها proxy أو تصديرًا افتراضيًا، لذلك يفشل export function middleware. غيّر اسمها إلى proxy، أو شغّل npx @next/codemod@canary middleware-to-proxy .

هل يمكنني الإبقاء على middleware.ts في Next.js 16؟

نعم، حاليًا. في Next.js 16.4.5 ما زال middleware.ts ينجح بناؤه ويعمل، مع تحذير بأنه مهجور. وهو أيضًا الخيار الموثّق إذا كنت تحتاج إلى بيئة Edge. لكن لا تتركه أبدًا بجانب proxy.ts: يتوقف البناء عند وجود الملفين.

هل يعمل next-intl مع proxy.ts؟

نعم. تستخدم وثائق next-intl الملف src/proxy.ts مع export default createMiddleware(routing); والـ matcher '/((?!api|trpc|_next|_vercel|.*\\..*).*)'. بنيناه وشغّلناه مع next-intl 4.14.9 على Next.js 16.4.5.

لماذا ينجح البناء ثم تعيد كل صفحة الخطأ 500؟

غالبًا لأن التصدير الافتراضي ليس دالة، بل كائنًا مثلًا. قبله البناء في اختبارنا، ثم فشل كل طلب مع الرسالة «The Proxy file "/proxy" must export a function named `proxy` or a default function.». صدّر دالة بدلًا منه.

أين أضع proxy.ts إذا كنت أستخدم مجلد src؟

في src/proxy.ts بجانب src/app. في هذا التنظيم يتجاهل Next.js أي proxy.ts في الجذر دون رسالة خطأ، فتأكد أن next build يعرض ƒ Proxy (Middleware).

هل يختلف الخطأ مع webpack؟

تختلف الصياغة فقط. مع next build --webpack تكون الرسالة «The file "./proxy.ts" must export a function, either as a default export or as a named "proxy" export.». والحل نفسه.

الخلاصة

يعود هذا الخطأ دائمًا إلى سطر واحد: سطر التصدير. سمِّ الدالة proxy أو صدّرها افتراضيًا، وأبقِ الملف بجانب app، واحذف middleware.ts القديم. ومع next-intl يكون هذا السطر export default createMiddleware(routing);. بعد ذلك تأكد أن next build يعرض الـ proxy، وأرسل طلبًا حقيقيًا قبل النشر.

قوالب فيها proxy.ts وnext-intl جاهزان

إذا فضّلت أن تبدأ من كود يعمل فيه كل هذا مسبقًا، فكل قوالب Aniq UI المدفوعة تعمل على Next.js 16 مع src/proxy.ts وnext-intl، بالإنجليزية والعربية مع تخطيط حقيقي من اليمين إلى اليسار. فتحنا المستودعات يوم 5 نوفمبر 2026: كل تطبيق فيها على Next.js 16.3 أو 16.4، والحلّان المشروحان هنا مستخدمان فيها. صفحة هبوط SaaS تستخدم export default createMiddleware(routing)، وقالب المطعم يستخدم export async function proxy.

لوحة تحكم قالب المطعم من Aniq UI بالعربية بالوضع الداكن: الشريط الجانبي على اليمين، ومخطط الإيرادات، وقائمة الطلبات، وأعمدة الفئات

قالب صفحة هبوط SaaS من Aniq UI بالوضع الداكن، مع مبدّل اللغة في الشريط العلوي ومعاينة للوحة تحليلات أسفل القسم الرئيسي

سعر كل نوع، بدفعة واحدة، مع الكود المصدري:

  • المواقع والمتاجر (مطاعم، عقارات، منصات تعليم، متاجر إلكترونية، تأجير سياحي، بيع تذاكر الفعاليات): $39.
  • صفحات الهبوط (SaaS وPublino): $39.
  • لوحات التحكم: من $49 (لوحة التحكم المالية بسعر $49، ولوحة التحكم بالمساعد الذكي ولوحة اللياقة البدنية بسعر $69).
  • الـ API الخلفي: $99.
  • Full Stack (الموقع ولوحة التحكم والـ API معًا): $149.
  • القوالب العشرة كلها: الحزمة، بسعر قائمة $499. راجع الصفحة لمعرفة العرض الحالي.

تصفّح القوالب وافتح أي عرض حي بالعربية قبل الشراء.

المصادر

اختُبر مع Next.js 16.4.5 وnext-intl 4.14.9 وReact 19.3.1 وTypeScript 5.9.3 على Node.js 24.17.0. تمت المراجعة في نوفمبر 2026.

هل وجدت هذا المقال مفيدًا؟

مشاركة:
النشرة البريدية

احصل على إشعار عند إطلاق قالب جديد

كن أول من يعلم عند إصدار قالب جديد.

  • إصدارات القوالب الجديدة
  • تابع ما يُبنى الآن وصوّت عليه
  • إصدارات مجانية ومدفوعة
  • إلغاء الاشتراك بنقرة واحدة

القادم قريباً

world map

مجتمع المستخدمين العالمي

انضم إلى آلاف المطورين في جميع أنحاء العالم الذين يثقون بـ Aniq-UI لمشاريعهم. يتم استخدام قوالبنا في جميع أنحاء العالم لإنشاء تجارب ويب مذهلة.

Aniq-uiAniq-ui

تفضيلات ملفات تعريف الارتباط

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