الترحيل من Pages Router إلى App Router في Next.js 16 عملية تدريجية آمنة يمكن إجراؤها مسارًا مسارًا لأن كلا الموجّهَين يعملان جنبًا إلى جنب في المشروع نفسه. تبدأ بتشغيل الـ codemod الرسمي عبر npx @next/codemod@latest app-router-migration، ثم تعالج يدويًا الواجهات غير المتزامنة الجديدة (params, searchParams, cookies(), headers())، وأخيرًا تنقل مسارات pages/api/* إلى Route Handlers. من واقع تجربتي في ترحيل فِرَق كاملة، متوسط الجهد يتراوح بين 3 أيام لمشروع صغير و20 يوم عمل لتطبيق مؤسسي بعدة عشرات من الصفحات.
يشترط Next.js 16 وجود Node.js 20.9 أو أحدث. الإصدار 18 لم يعد مدعومًا وسيفشل البناء فورًا.
الموجّهان (Pages وApp) يعملان في المشروع نفسه، مما يسمح بترحيل تدريجي مسارًا مسارًا دون تجميد المنتج.
الـ codemod الرسمي يعالج الاستيرادات وتحويل _app/_document وnext/router، لكنه لا يعالج دلالات cookies() وheaders() غير المتزامنة.
middleware.ts أعيدت تسميته إلى proxy.ts في Next.js 16 وتغيّرت واجهته البرمجية.
معظم أخطاء الترحيل تأتي من التعامل مع params كقيمة متزامنة بدلًا من Promise.
الجهد الفعلي: 3 أيام لمشروع صغير (<10 صفحات)، 8–12 يومًا لمشروع متوسط، حتى 20 يومًا لتطبيق مؤسسي.
لماذا الترحيل الآن في 2026؟
في أبريل 2026 أصدرت Vercel النسخة Next.js 16 وحسمت اتجاه المكتبة. كل ميزة جديدة تُبنى على App Router فقط: Server Actions، وPartial Prerendering (PPR)، وuse cache، وSuspense streaming، وتحسينات React 19 كلها غير متاحة للموجّه القديم. الموجّه Pages Router لا يزال مدعومًا ولن يُحذف قريبًا، لكنه دخل مرحلة الصيانة فحسب (لا ميزات، فقط إصلاحات أمنية).
لوحة تحكم Vercel أصبحت تصنّف المشاريع التي تعتمد على Pages Router فقط بعلامة "legacy"، وأدوات القياس الجديدة مثل Speed Insights تعرض توصيات ترحيل صريحة. من ناحية الأداء، تقارير 2026 من فريق Next.js تشير إلى أن تطبيقات App Router تشحن في المتوسط 40–60٪ أقل من JavaScript إلى المتصفح بفضل React Server Components. الفارق يظهر جليًا في مقاييس Core Web Vitals، خاصة LCP وTBT، وهو ما ينعكس مباشرة على ترتيب Google.
الأهم من ذلك أن مكتبة التوثيق الرسمية أعادت هيكلة الأمثلة حول App Router. إذا احتجت مساعدة في مشكلة جديدة، فإن 90٪ من إجابات 2026 تفترض أنك تستخدم App Router. تأجيل الترحيل يعني تراكم دَين تقني يزيد كلفته سنويًا.
Pages Router مقابل App Router: مقارنة سريعة
قبل أن تكتب سطرًا من الترحيل، تحتاج نموذجًا ذهنيًا واضحًا للفروق الجوهرية. هذه المقارنة تلخّص ما ستواجهه فعليًا في القاعدة البرمجية:
التحوّل الأهم ليس في بنية المجلدات، بل في التفكير على أساس حدود Server/Client بدلًا من دوال بيانات على مستوى الصفحة. صراحةً، هذا هو الجزء الذي يستهلك أكبر وقت في المراجعات مع أعضاء الفريق الجدد. إذا كنت جديدًا على هذا النموذج، اقرأ أولًا دليل مكونات الخادم والعميل في Next.js App Router قبل البدء.
قائمة ما قبل الترحيل والتدقيق
الاندفاع إلى تشغيل الـ codemod دون تخطيط هو أول خطأ في كل مشروع ترحيل رأيته يفشل. اقضِ يومًا كاملًا في التدقيق قبل تعديل أي ملف. (نعم، يومًا كاملًا. سيوفّر عليك أسبوعًا لاحقًا.)
1. تحديث الأدوات
Next.js 16 يشترط Node.js 20.9.0 على الأقل. تحقق من إصدارك:
node --version # يجب أن يكون >= 20.9.0
# ترقية Next.js إلى 16.x
npm install next@latest react@latest react-dom@latest
npm install --save-dev @types/react@latest @types/node@latest
2. جرد المسارات وتصنيفها
أنشئ جدول بيانات بسيطًا يسرد كل مسار (route) في pages/ ويصنّفه ضمن ثلاثة مستويات مخاطر:
منخفض: صفحات ثابتة، صفحات تسويقية، صفحات محتوى تعتمد getStaticProps بلا مصادقة.
متوسط: صفحات تستخدم getServerSideProps مع منطق أعمال بسيط.
مرتفع: تدفقات الدفع، لوحات التحكم، أي مسار يعتمد على getInitialProps أو تخصيص عميق لـ _app/_document.
ابدأ بالمخاطر المنخفضة، ولا تلمس المخاطر المرتفعة إلا بعد أن يكون فريقك مرتاحًا مع النموذج الجديد.
3. قياس خط الأساس
سجّل مقاييس أداء ما قبل الترحيل قبل أي تغيير: LCP، وFID/INP، وحجم حزمة JS، ووقت البناء. هذه الأرقام هي معيار النجاح، وستحتاجها لاحقًا لإقناع الإدارة بأن الاستثمار كان مبرَّرًا.
تشغيل الـ codemod الرسمي
وفّر فريق Next.js حزمة @next/codemod التي تشغّل سلسلة تحويلات تلقائية. الوصفة الجامعة لترحيل App Router تشغّل عدة codemods بالترتيب الصحيح دفعة واحدة:
# تشغيل وصفة الترحيل الكاملة
npx @next/codemod@latest app-router-migration ./
# أو تشغيل codemods فردية
npx @next/codemod@latest next-async-request-api ./
npx @next/codemod@latest built-in-next-font ./
npx @next/codemod@latest next-image-to-legacy-image ./
تحويل params وsearchParams إلى Promise غير متزامن.
نقل _app.tsx و_document.tsx إلى app/layout.tsx واحد.
تغيير استيراد next/router إلى الخطافات الثلاثة من next/navigation (useRouter, usePathname, useSearchParams).
استبدال getStaticPaths بـ generateStaticParams.
تسمية استيرادات next/image القديمة إلى next/legacy/image.
التغييرات اليدوية التي لا يعالجها الـ codemod
الـ codemod يعالج الاستيرادات وبعض الأنماط، لكنه لا يعالج دلالات كائن الطلب، ولا واجهات cookies/headers غير المتزامنة، ولا حدود Suspense، ولا ترحيل Route Handlers. تعامل معه كنقطة بداية لا كترحيل كامل.
1. تحويل قراءة params إلى async
في Pages Router:
// pages/blog/[slug].tsx
export async function getServerSideProps({ params }) {
const post = await fetchPost(params.slug);
return { props: { post } };
}
export default function Post({ post }) {
return <article>{post.title}</article>;
}
في App Router بعد Next.js 16:
// app/blog/[slug]/page.tsx
type Props = { params: Promise<{ slug: string }> };
export default async function Post({ params }: Props) {
const { slug } = await params; // ← يجب await
const post = await fetchPost(slug);
return <article>{post.title}</article>;
}
2. cookies و headers أصبحت غير متزامنة
// قديم (Pages Router أو App Router قبل 15)
import { cookies } from 'next/headers';
const session = cookies().get('session');
// جديد (Next.js 16)
import { cookies } from 'next/headers';
const cookieStore = await cookies();
const session = cookieStore.get('session');
صراحةً، هذا هو الخطأ الأول الذي يسقط فيه معظم المطوّرين. TypeScript لن يمسكه إن تركت مكتبة قديمة تصدّر توقيعًا متزامنًا. اعتمد على تعريفات TypeScript الرسمية الأحدث حصرًا.
3. Client Components تستقبل params كـ Promise
إذا كنت تمرر params أو searchParams إلى Client Component، فك التغليف عبر use() من React:
'use client';
import { use } from 'react';
type Props = { params: Promise<{ slug: string }> };
export default function ClientView({ params }: Props) {
const { slug } = use(params);
return <div>Viewing: {slug}</div>;
}
4. جلب البيانات: من دوال إلى async في المكوّن
ثلاث دوال قديمة تختفي وتُستبدَل بنمط واحد:
getServerSideProps → fetch(url, { cache: 'no-store' }) داخل مكوّن خادم.
getStaticProps → fetch(url) افتراضيًا (يُخزَّن مؤقتًا في build).
مسارات الـ API تحتاج انتقالًا يدويًا حتى بعد الـ codemod. الاختلاف في الواجهة البرمجية جوهري وليس مجرد إعادة تسمية.
الشكل القديم في Pages Router
// pages/api/users/[id].ts
import type { NextApiRequest, NextApiResponse } from 'next';
export default async function handler(
req: NextApiRequest,
res: NextApiResponse,
) {
if (req.method === 'GET') {
const user = await getUser(req.query.id as string);
return res.status(200).json(user);
}
res.status(405).end();
}
الشكل الجديد في App Router
// app/api/users/[id]/route.ts
import { NextResponse } from 'next/server';
type Ctx = { params: Promise<{ id: string }> };
export async function GET(request: Request, ctx: Ctx) {
const { id } = await ctx.params;
const user = await getUser(id);
return NextResponse.json(user);
}
export async function DELETE(request: Request, ctx: Ctx) {
const { id } = await ctx.params;
await deleteUser(id);
return new NextResponse(null, { status: 204 });
}
لاحظ الفرق: كل فعل HTTP يصبح دالة مُصدَّرة بأحرف كبيرة (GET, POST, PATCH, DELETE)، بدلًا من التبديل داخل handler واحد. هذا يعطي Next.js فرصة تحسين الحزمة لكل فعل على حدة. للتعمق راجع دليل Route Handlers في Next.js 16.
من middleware.ts إلى proxy.ts
واحدة من أكبر التغييرات الاسمية في Next.js 16 هي إعادة تسمية middleware.ts إلى proxy.ts، لتعكس دوره الفعلي كوكيل خفيف على الحافة (edge proxy) لا كطبقة معالجة عامة. الحركة ليست مجرد تغيير اسم. بعض الواجهات البرمجية تغيّرت أيضًا.
// proxy.ts (كان middleware.ts)
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function proxy(request: NextRequest) {
const session = request.cookies.get('session');
if (!session && request.nextUrl.pathname.startsWith('/dashboard')) {
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ['/dashboard/:path*', '/api/protected/:path*'],
};
لتغطية شاملة لكل التغييرات في الوسيط، انظر دليل Middleware و proxy.ts في Next.js 16. الـ codemod الرسمي يعيد تسمية الملف تلقائيًا لكن يجب أن تراجع كل استخدام لواجهة الطلب يدويًا.
تشغيل الموجّهَين معًا أثناء الترحيل
الميزة الأهم في هذه العملية أن كلا الموجّهَين يعملان في المشروع نفسه بشرط ألا يتصادما على المسار ذاته. القاعدة بسيطة: إذا وُجد app/foo/page.tsx، فسيتجاهل Next.js pages/foo.tsx. لا شيء ينكسر ما دمت لم تكرر المسار في المكانين.
هذا يفتح استراتيجية "الترحيل التدفقي": ابدأ بالصفحات الثابتة (about، pricing، docs)، ثم صفحات المحتوى، ثم لوحات التحكم، ثم تدفقات الدفع. كل PR ينقل مسارًا واحدًا، يمر بمراجعة، وينشر إلى الإنتاج مستقلًا. لا يوجد "big bang".
my-app/
├── app/ ← الجديد
│ ├── layout.tsx
│ ├── about/
│ │ └── page.tsx ← تم ترحيله
│ └── api/
│ └── health/
│ └── route.ts
├── pages/ ← القديم (يعمل)
│ ├── _app.tsx ← ما زال مطلوبًا لصفحات pages/
│ ├── checkout.tsx ← لم يُرحَّل بعد
│ └── api/
│ └── stripe.ts ← لم يُرحَّل بعد
└── next.config.js
كم يستغرق الترحيل فعلًا؟
من واقع أربعة مشاريع ترحيل نفّذتها لفِرَق مختلفة في 2025 و2026، هذه الأرقام التقريبية بيوم-مطوّر واحد:
حجم المشروع
عدد المسارات
الجهد التقديري
ملاحظات
صغير
< 10 صفحات
2–3 أيام
الـ codemod يغطي 80٪ من العمل
متوسط
10–40 صفحة
8–12 يومًا
يشمل إعادة كتابة API Routes
كبير
40–100 صفحة
15–20 يومًا
ترحيل تدريجي عبر 4–6 أسابيع
مؤسسي
> 100 صفحة
25+ يومًا
يحتاج فريقًا وخطة إصدار متدرجة
هذه الأرقام تفترض مطوّرًا مألوفًا بـ Next.js. إذا كان الفريق يتعلم App Router للمرة الأولى، أضف 30–50٪ لمنحنى التعلّم، خاصة حول Server Actions والحدّ بين Server وClient.
الأخطاء الشائعة وكيفية تجنبها
1. الاعتماد الأعمى على الـ codemod
الفشل الأكثر شيوعًا: تشغيل الـ codemod، رؤية أن التطبيق يبني بنجاح، والدمج مباشرة. الـ codemod لا يمسك الفروق في كائن الطلب، ولا الانقسام بين next/router وnext/navigation، ولا نمط cookies/headers الجديد. استخدم الـ diff كقائمة تدقيق لا كالتزام نهائي.
2. الترحيل الدفعي "big bang"
الخطأ الأكثر تكلفة: محاولة تحويل كل شيء دفعة واحدة في PR ضخم. رحّل صفحاتك الأبسط والأكثر حركة أولًا، تحقّق من الأداء والسلوك في الإنتاج، ثم تابع مع المسارات الأعقد.
3. تجاهل حدود Server/Client
ستُغرَى بإضافة 'use client' إلى كل مكوّن ليعمل الكود القديم فورًا. لا تفعل. هذا يبطل فائدة App Router كاملة. اجعل الاستخدام الافتراضي Server Component، وأنزل 'use client' إلى أوراق الشجرة (leaf components) فقط. راجع أنماط التركيب في دليل Server Actions للنماذج والتحقق.
4. نسيان تحديث اختبارات E2E
معظم فِرَق QA لديها اختبارات Cypress أو Playwright تعتمد على selectors محددة أو أوقات تحميل معينة. Streaming يغيّر توقيت ظهور العناصر، وسيبدو الاختبار "متعطلًا" بينما التطبيق يعمل. حدّث انتظارات الاختبار لتستخدم waitFor بدلًا من مدد ثابتة.
5. تخطي مرحلة قياس ما بعد الترحيل
بدون قياس مقاييس Core Web Vitals قبل وبعد، لن تعرف إن كان الترحيل حقق قيمته. استخدم Vercel Speed Insights أو أي أداة RUM لمقارنة LCP وINP وCLS لكل مسار قبل وبعد.
أسئلة شائعة
كم يستغرق الترحيل من Pages إلى App Router؟
مشروع صغير (<10 صفحات) يحتاج 2–3 أيام. مشروع متوسط 8–12 يومًا. مشروع مؤسسي (>100 صفحة) قد يمتد إلى 25 يومًا أو أكثر عبر 4–8 أسابيع من الترحيل التدريجي. الـ codemod يوفّر حوالي 60٪ من الوقت لكنه لا يعالج التغييرات الدلالية.
هل يمكن استخدام Pages Router و App Router معًا في نفس المشروع؟
نعم، هذا هو المسار الموصى به رسميًا من Vercel. كل مسار موجود في app/ يأخذ الأولوية على نظيره في pages/، لذا يمكنك ترحيل صفحة واحدة، إصدارها، وترك البقية على Pages Router. لا شيء ينكسر ما لم تكرر المسار في المكانين.
ما الذي ينكسر عند الترحيل إلى App Router؟
أكثر ما ينكسر: قراءة params وsearchParams كقيم متزامنة (أصبحت Promises)، استدعاءات cookies() وheaders() بدون await، الاعتماد على getInitialProps، وأي معالج API يفترض توقيع NextApiRequest/Response. الـ codemod يمسك بعضها لكن ليس كلها.
هل App Router أسرع من Pages Router؟
نعم في معظم الحالات. تطبيقات App Router تشحن 40–60٪ أقل من JavaScript إلى المتصفح بفضل React Server Components، مما يحسّن LCP وTBT بشكل ملحوظ. الفارق يظهر بوضوح في الصفحات المحتوى-كثيفة، وأقل وضوحًا في تطبيقات SaaS تفاعلية شديدة الديناميكية.
هل يجب علينا الترحيل إلى App Router الآن؟
إذا كنت تبدأ مشروعًا جديدًا، نعم بلا استثناء. إذا كان لديك تطبيق إنتاجي مستقر على Pages Router، لا يوجد ضغط عاجل. الدعم مستمر حتى Next.js 18 على الأقل. لكن كل ميزة جديدة (Server Actions, PPR, use cache) حصرية للـ App Router، لذا تأجيل الترحيل يعني تراكم دَين تقني.
دليل عملي لبناء واجهات HTTP في Next.js 16 عبر Route Handlers: من إعداد route.ts إلى البث والتخزين المؤقت وCORS، مع أمثلة كود جاهزة وشرح واقعي من الإنتاج.
دليل عملي شامل لـ Turbopack في Next.js 16 من منظور مهندس معماري للواجهة: ترحيل webpack، ضبط ذاكرة build الإنتاج على Vercel، تكوين monorepo مع pnpm، وقياسات أداء ميدانية مقابل Webpack.
كل ما تحتاجه لتفعيل PPR في Next.js 16 خطوة بخطوة: التكوين، حدود Suspense، الفرق عن ISR وSSR، الدمج مع use cache، أخطاء شائعة، ونصائح نشر على Vercel و Node.js و Edge.