دليل الانتقال إلى Next.js 16: ترقية خطوة بخطوة
تحديث مشروع Next.js بين الإصدارات الرئيسية لا يكون في العادة ببساطة تشغيل npm install next@latest ثم متابعة العمل. فعندما يكون المشروع مستخدماً في بيئة production ويعتمد على authentication أو middleware أو caching أو image optimization أو إعدادات build مخصصة، يمكن أن يؤثر تحديث framework مباشرة في بنية التطبيق.
وهذا ينطبق بشكل واضح على Next.js 16.
صدر الإصدار الأول من Next.js 16 في أكتوبر 2025، وجعل Turbopack أداة bundler الافتراضية، وأعاد النظر في نموذج caching، وقدم دعماً لـ React Compiler إلى جانب تحسينات في routing وعدد من breaking changes التي قد تتطلب تعديلات مباشرة في الكود أثناء migration. ولم يتوقف التطوير عند ذلك، إذ صدر Next.js 16.3 في 3 أغسطس 2026 مع تحسينات إضافية في الأداء وتجربة المطور.
لذلك لن نكتفي في هذا المقال بالسؤال: «ما الجديد في Next.js 16؟». السؤال الأكثر أهمية هو:
ما الذي يمكن أن يتعطل عند نقل مشروع قائم من Next.js 15 إلى Next.js 16، وكيف يمكن تنفيذ migration بطريقة آمنة ومنظمة؟
ابدأ بفحص بيئة التشغيل
قبل بدء migration، أول ما أفضّل مراجعته ليس framework نفسه، بل بيئة التشغيل. والسبب أن Next.js 16 غيّر أيضاً الحد الأدنى لمتطلبات النظام.
يتطلب Next.js 16 إصدار Node.js 20.9.0 على الأقل، وTypeScript 5.1.0 على الأقل. ولم يعد Node.js 18 مدعوماً.
ابدأ بفحص إصدار Node.js الحالي:
node -v
إذا كان المشروع يستخدم Docker، فلا يكفي تحديث البيئة المحلية فقط. يجب أيضاً مراجعة Node image داخل Dockerfile، وCI/CD pipeline، وإصدار Node.js الموجود على production server.
على سبيل المثال، إذا كان Dockerfile القديم يحتوي على:
FROM node:18-alpine
فيجب نقله إلى إصدار مدعوم من Node 20 عند الانتقال إلى Next.js 16.
هذه واحدة من أكثر النقاط التي يسهل تجاهلها في major framework migrations: يعمل التطبيق محلياً بشكل طبيعي بينما لا تزال بيئة production build تستخدم إصداراً قديماً من Node.js.

كيف ننتقل إلى Next.js 16؟
يوفر فريق Next.js أداة codemod مخصصة لهذه العملية.
إذا كنت تستخدم npm:
npx @next/codemod@canary upgrade latest
أما إذا كنت تفضّل التحديث يدوياً:
npm install next@latest react@latest react-dom@latest
وفي المشاريع التي تستخدم TypeScript، يجب أيضاً تحديث حزم أنواع React:
npm install -D @types/react@latest @types/react-dom@latest
أفضّل عادة البدء باستخدام codemod كلما كان ذلك ممكناً. فهو لا يغيّر إصدارات dependencies فقط، بل يمكنه أيضاً تحديث Turbopack configuration، ونقل استخدام next lint إلى ESLint CLI، وتحويل convention الخاص بـ middleware إلى proxy، وتنظيف بعض إعدادات experimental القديمة.
لكن هناك فرق مهم:
يسهّل codemod عملية migration، لكنه لا ينفذها بالكامل بدلاً منك.
يجب الاستمرار في اختبار custom Webpack configuration والحزم الخارجية وطبقة authentication وسلوك caching بشكل يدوي.
Turbopack أصبح الخيار الافتراضي
هذه من أهم التغييرات التي يجب الانتباه إليها عند الانتقال إلى Next.js 16.
ابتداءً من Next.js 16 أصبح Turbopack هو bundler الافتراضي لكل من next dev وnext build. ولم تعد هناك حاجة إلى تمرير --turbo أو --turbopack بشكل منفصل.
الاستخدام السابق:
{
"scripts": {
"dev": "next dev --turbopack",
"build": "next build --turbopack"
}
}
الاستخدام الجديد:
{
"scripts": {
"dev": "next dev",
"build": "next build"
}
}
المشكلة تبدأ في المشاريع التي تحتوي على custom Webpack configuration.
إذا كان next.config.js يحتوي على تعريف مخصص لـ webpack()، فقد يؤدي انتقال Next.js 16 مباشرة إلى Turbopack إلى نتائج غير متوقعة. وفي بعض الحالات يمكن أن يوقف Next.js عملية build بدلاً من الاستمرار باستخدام configuration غير متوافق.
إذا كنت بحاجة إلى الاستمرار باستخدام Webpack:
next dev --webpack
next build --webpack
أصبح Turbopack ناضجاً إلى حد كبير، لكنه لا يقدم بعد بديلاً مطابقاً بالكامل لكل Webpack plugin. لذلك يجب فحص المشاريع الكبيرة التي تعتمد على Sentry أو custom loaders أو عمليات Sass مخصصة أو Webpack plugins أخرى قبل migration.
بدلاً من اتباع منطق «وصل Turbopack، إذن سأحذف Webpack مباشرة»، أفضّل أولاً مقارنة development وproduction build باستخدام الأداتين.
أصبحت params وsearchParams وcookies() وheaders() غير متزامنة بالكامل
كان Next.js 15 قد بدأ بالفعل في تهيئة المطورين لهذا التغيير.
أصبحت request-time API مثل params وsearchParams وcookies() وheaders() وdraftMode() asynchronous في Next.js 15. ولكن كان من الممكن استخدام الوصول المتزامن مؤقتاً للحفاظ على backward compatibility.
في Next.js 16 انتهى هذا الدعم.
تمت إزالة الوصول المتزامن بالكامل.
على سبيل المثال، كان من الممكن سابقاً كتابة:
export default function Page({
params,
}: {
params: { slug: string }
}) {
const { slug } = params
return <div>{slug}</div>
}
أما في Next.js 16 فيجب أن يصبح:
export default async function Page({
params,
}: {
params: Promise<{ slug: string }>
}) {
const { slug } = await params
return <div>{slug}</div>
}
وينطبق الأمر نفسه على cookies().
الاستخدام السابق:
import { cookies } from 'next/headers'
const cookieStore = cookies()
const token = cookieStore.get('token')
الاستخدام الجديد:
import { cookies } from 'next/headers'
const cookieStore = await cookies()
const token = cookieStore.get('token')
في مشاريع App Router الكبيرة، ستكون هذه من أولى النقاط التي أبحث عنها بعد migration.
ولا يقتصر الأمر على ملفات page.tsx. فقد يتم استخدام params أيضاً داخل layouts وRoute Handlers وgenerateMetadata وOpen Graph image routes وأجزاء أخرى من التطبيق.
كما يمكن لـ Next.js إنشاء type helper مثل PageProps وLayoutProps وRouteContext باستخدام:
npx next typegen
middleware.ts يفسح المجال لـ proxy.ts
هناك تغيير ملحوظ آخر يتعلق بالتسمية.
في Next.js 16 أصبح convention الخاص بـ middleware.ts deprecated، وحل محله proxy.ts. والهدف هو توضيح أن هذه الطبقة ليست middleware عامة على طريقة Express، بل تعمل عند network boundary أمام التطبيق.
سابقاً:
// middleware.ts
export function middleware(request: NextRequest) {
// ...
}
الآن:
// proxy.ts
export function proxy(request: NextRequest) {
// ...
}
كما يوجد codemod منفصل لتنفيذ migration:
npx @next/codemod@canary middleware-to-proxy .
ولا يقتصر التغيير على اسم الملف. بل يُنصح أيضاً بتغيير اسم الدالة المصدّرة من middleware إلى proxy.
لكن النقطة الأكثر أهمية تتعلق بالـ runtime.
يعمل proxy.ts على Node.js runtime ولا يمكن تغيير runtime يدوياً. لذلك يجب تقييم Middleware implementations الحالية التي تعتمد على Edge runtime بشكل منفصل.
إذا كان المشروع يستخدم Middleware بشكل مكثف في authentication أو locale redirects أو rewrites أو authorization، فيجب اختبار هذا الجزء بعناية.
تمت إزالة next lint
قد يبدو هذا التغيير بسيطاً، لكنه قد يؤدي بسهولة إلى تعطل CI pipeline.
في Next.js 16 تمت إزالة:
next lint
كما أن next build لم يعد يشغّل lint تلقائياً. فقد تم فصل عملية linting عن framework build، وأصبح من المتوقع استخدام ESLint CLI مباشرة.
إذا كان package.json يحتوي على:
{
"scripts": {
"lint": "next lint"
}
}
يمكن تغييره مثلاً إلى:
{
"scripts": {
"lint": "eslint ."
}
}
كما يمكن أن يساعد migration codemod في هذا التحويل.
إذا كان CI/CD pipeline يشغّل npm run lint قبل build، فيجب إضافة هذه النقطة إلى migration checklist.
تغيرت القيم الافتراضية في next/image
أجرى Next.js 16 أيضاً بعض التغييرات على defaults الخاصة بـ image optimization.
على سبيل المثال، ارتفعت القيمة الافتراضية لـ images.minimumCacheTTL من 60 ثانية إلى 4 ساعات. كما أصبحت [75] هي القيمة الافتراضية لجودة الصور بدلاً من النطاق الأوسع السابق.
إذا كان المشروع يستخدم:
<Image
src="/product.jpg"
width={800}
height={600}
quality={100}
alt="Product"
/>
وأردت الحفاظ على quality={100}، فقد تحتاج إلى تعريف ذلك صراحة في configuration:
const nextConfig = {
images: {
qualities: [50, 75, 100],
},
}
export default nextConfig
هناك أيضاً breaking change آخر يتعلق باستخدام query string داخل local image URLs.
على سبيل المثال:
<Image
src="/assets/product.jpg?v=2"
width={500}
height={500}
alt="Product"
/>
إذا كنت تستخدم URLs من هذا النوع، فقد تحتاج الآن إلى تعريف images.localPatterns بشكل مناسب.
هذه النقطة مهمة بشكل خاص في مشاريع e-commerce وCMS، حيث تكون image URLs ديناميكية في كثير من الأحيان.
Cache Components تجعل caching أكثر وضوحاً
كان caching من أكثر المواضيع إرباكاً في الإصدارات الرئيسية الأخيرة من Next.js.
أسئلة مثل «لماذا تم cache لهذا fetch؟» و«لماذا أصبح هذا route static؟» و«لماذا لم تظهر revalidation مباشرة؟» مألوفة تقريباً لكل من عمل مع App Router.
في Next.js 16 تتجه هذه المنظومة إلى نموذج أكثر explicit.
يمكن تفعيل Cache Components عبر:
const nextConfig = {
cacheComponents: true,
}
export default nextConfig
ثم يسمح directive "use cache" بالتحكم بشكل أوضح في component أو function التي يجب تخزينها مؤقتاً. كما انتقل نهج experimental.ppr السابق إلى نموذج Cache Components.
هناك نقطة مهمة هنا:
لست مضطراً إلى استخدام Cache Components لمجرد أنك تنتقل إلى Next.js 16.
أثناء migration، لا أفضّل إعادة تصميم caching architecture بالكامل في نفس commit. من الأفضل أولاً تثبيت migration إلى framework الجديد، ثم التعامل مع Cache Components كمهمة منفصلة.
الجمع بين major version migration وتغيير caching architecture في الوقت نفسه يجعل تحديد مصدر الخطأ أكثر صعوبة.
تغير revalidateTag() ووصل updateTag()
هناك أيضاً تغييرات مهمة على مستوى caching API.
أصبح الأسلوب الموصى به لـ revalidateTag() هو استخدام معامل ثانٍ لتحديد cacheLife profile:
import { revalidateTag } from 'next/cache'
revalidateTag('blog-posts', 'max')
يؤدي ذلك إلى اعتبار cache الحالي stale وفق أسلوب stale-while-revalidate، ثم جلب المحتوى الجديد في background.
أما الاستخدام بمعامل واحد فأصبح deprecated.
كما يقدم Next.js 16 API جديداً باسم updateTag().
'use server'
import { updateTag } from 'next/cache'
export async function updateProfile() {
// database update
updateTag('user-profile')
}
تم تصميم updateTag() للحالات التي يجب أن يرى فيها المستخدم أحدث نسخة من البيانات فوراً بعد إجراء تعديل. ويمكن استخدام API فقط داخل Server Actions.
يمكن تلخيص الفرق بالنسبة لي كالتالي:
استخدم revalidateTag() للمحتوى مثل المدونات والكتالوجات والتوثيق، حيث لا تمثل بضع ثوانٍ من التأخير مشكلة. واستخدم updateTag() عندما يحتاج المستخدم إلى رؤية تغييره فوراً.
React Compiler أصبح Stable، لكنك لست مضطراً لتفعيله
أصبح دعم React Compiler stable في Next.js 16.
يهدف React Compiler إلى تقليل عمليات render غير الضرورية من خلال memoization تلقائية للـ components. لكنه غير مفعّل افتراضياً.
لتفعيله:
const nextConfig = {
reactCompiler: true,
}
export default nextConfig
كما يجب تثبيت حزمة compiler:
npm install -D babel-plugin-react-compiler
وأفضّل اتباع النهج نفسه هنا أثناء migration:
أكمل أولاً migration إلى Next.js 16 وتأكد من application behavior، ثم قيّم React Compiler كخطوة optimization منفصلة.
يضيف React Compiler عملاً إضافياً إلى build pipeline، ولذلك يمكن أن ترتفع مدة development وproduction build.
ما الذي يجب اختباره بعد الانتقال إلى Next.js 16؟
نجاح code compilation لا يعني أن migration اكتملت.
قبل الانتقال إلى production أفضّل التحقق من النقاط التالية:
- هل تستخدم Node.js وTypeScript وReact وNext.js بإصدارات مدعومة؟
- هل تعمل development وproduction build بشكل صحيح مع Turbopack؟
- إذا كان هناك custom Webpack configuration، فهل تمت مراجعة توافقه مع Turbopack؟
- هل تمت إزالة الاستخدامات المتزامنة لـ
paramsوsearchParamsوcookies()وheaders()وdraftMode()؟ - هل تمت مراجعة migration من
middleware.tsإلىproxy.ts؟ - هل تعمل authentication وredirects وrewrites وlocale routing بشكل صحيح؟
- هل تم تحديث scripts وCI pipelines التي تستخدم
next lint؟ - هل تم اختبار quality وcache وlocal URL الخاصة بـ
next/image؟ - هل يعمل ISR وcache invalidation وتحديث البيانات بعد Server Actions كما هو متوقع؟
- هل تم اختبار dynamic routes و
generateMetadata؟ - هل تم فحص صفحات production المهمة باستخدام Lighthouse ومسارات استخدام حقيقية؟
ومن الأفضل أيضاً تنفيذ migration في branch منفصل ومقارنة build الجديد على Next.js 16 بالإصدار الحالي على Next.js 15 بدلاً من تنفيذ التحديث مباشرة في production branch.
كيف ينبغي التخطيط للانتقال إلى Next.js 16؟
لا ينبغي أن يكون الانتقال إلى إصدار رئيسي جديد هدفاً بحد ذاته. بالنسبة إلى تطبيق Next.js يتم تطويره باستمرار وسيظل مستخدماً لفترة طويلة، فإن البقاء قريباً من الإصدار الرئيسي الحالي يمكن أن يوفر مزايا مهمة من حيث تحديثات الأمان وتطور framework ودعم ecosystem.
لكن migration غير المخطط لها قد تضيف مخاطر غير ضرورية في تطبيقات production الكبيرة التي تعتمد بشكل كبير على custom Webpack plugins أو Edge Middleware أو السلوك القديم للـ framework.
لذلك من الأفضل التعامل مع major version migration كمشروع تقني صغير، وليس كمجرد تحديث عادي للـ dependencies.
للوهلة الأولى يبرز Next.js 16 بميزات مثل Turbopack وReact Compiler وCache Components. لكن عند migration لمشروع قائم، فإن breaking changes هي النقاط التي تحتاج إلى أكبر قدر من الاهتمام.
جعل Turbopack الخيار الافتراضي يؤثر على build pipeline، وasync Request APIs تؤثر على App Router code، والانتقال إلى proxy.ts يغيّر request layer، كما تؤثر تغييرات ESLint على CI/CD، ويمكن أن تؤثر caching APIs الجديدة مباشرة في استراتيجية تحديث البيانات.
أفضل ترتيب يمكن اتباعه واضح وبسيط:
التوافق أولاً، ثم migration، ثم optimization.
ابدأ بتحديث dependencies وبيئة التشغيل، ثم عالج breaking changes وتأكد من أن سلوك التطبيق الحالي ما زال يعمل كما هو متوقع. وبعد استقرار migration يمكن تفعيل ميزات مثل Turbopack وCache Components وReact Compiler بشكل تدريجي ومدروس.
لأن الانتقال إلى Next.js 16 واستخدام جميع ميزاته الجديدة في الوقت نفسه ليسا الشيء نفسه.
وبفضل codemods وأدوات upgrade التي يوفرها Next.js، فإن الانتقال من Next.js 15 إلى 16 لا يجب أن يكون معقداً أو مؤلماً إذا تم تنفيذ الخطوات بالترتيب الصحيح.
إذا كنت ترغب في تطوير تطبيق ويب قابل للتوسع وعالي الأداء باستخدام تقنيات حديثة، أو تحديث البنية التقنية لمشروع قائم، فيمكن لـ Detartech التعامل مع المشروع بشكل متكامل من خلال حلول تطوير الويب التي يقدمها.

