الترقية إلى Next.js 16: ما يفشل بصوت عالٍ وما يتغيّر بصمت
معظم التغييرات الكاسرة في الإصدار 16 توقف البناء، وهذا ما يجعلها آمنة. ما يستحق التخطيط له هو القليل منها الذي يغيّر السلوك دون أن يخبرك.
يحمل Next.js 16 قائمة طويلة من التغييرات الكاسرة، ومعظمها من النوع الجيد: يوقف البناء. تشغّلونه، فيفشل، فتُصلحونه، وتمضون.
ما يستحق القراءة بتمعّن هو القليل منها الذي يغيّر السلوك دون أن يفشل شيء. هذه هي التي تصل إلى الإنتاج.
كُتب هذا من قاعدة شيفرة تعمل على 16.3 - الموقع الذي تقرأونه الآن.
القرار المعماري الوحيد: صار middleware اسمه proxy
middleware.ts أصبح مهجورًا وتغيّر اسمه إلى proxy.ts، والدالة المصدَّرة
middleware صارت proxy. إعادة التسمية يتولّاها الـ codemod.
ما لا يستطيع الـ codemod تولّيه هو القرار الذي تحتها، وهو قرار حقيقي:
بيئة تشغيل
edgeغير مدعومة فيproxy. بيئة تشغيل proxy هيnodejsولا يمكن ضبطها.
إن كان الـ middleware لديكم يعمل على الحافة - وهذا كان السلوك الافتراضي - فإن إعادة تسمية الملف تنقل ذلك العمل من مئة موقع حافة إلى خادم Node واحد لديكم. بالنسبة لإعادة كتابة مسار أو تحويل لغوي يعمل مع كل طلب، هذا ليس إعادة تسمية، بل تغيير في مصدر زمن الاستجابة.
المسار الموثَّق إن كنتم تحتاجون بيئة الحافة هو الاستمرار على middleware في
الوقت الحالي. إذن في الترقية مفترق طرق:
- عمل توجيه خفيف - إعادة كتابة المسارات، التحويلات، قراءة كوكي - انقلوه
إلى
proxyواقبلوا بيئة Node. - أي شيء حسّاس لزمن الاستجابة على الحافة - ابقوا على
middlewareحتى تصدر الإرشادات التالية، مع العلم أنكم على اصطلاح مهجور.
في الحالتين، هذه هي اللحظة المناسبة للتحقق إن كان الـ matcher صحيحًا أصلًا في يوم من الأيام. الـ middleware يعمل مع كل طلب، بما فيها تلك التي نسيتموها - وكل واحد من تلك الطلبات صار الآن رحلةً إلى المصدر لديكم.
وتُعاد تسمية أعلام الإعداد معه: skipMiddlewareUrlNormalize صار
skipProxyUrlNormalize. هذه يتولّاها الـ codemod.
ما يفشل بصوت عالٍ، فلا تستطيعون نشره
إعداد webpack مع next build. صار Turbopack الافتراضي لـ next build
أيضًا، لا لـ next dev وحده، والمشروع الذي فيه إعداد webpack خاص يُفشل
البناء عمدًا بدل تجاهله بصمت. ثلاثة مخارج: البناء بـ --turbopack مع تجاهل
الإعداد، أو نقله إلى خيارات Turbopack، أو الانسحاب بـ --webpack. ومن
المفيد معرفته: قد تكون إضافة برمجية هي التي تضيف خيار webpack لم تكتبوه
أنتم، وهذه هي النسخة المربكة من هذا الخطأ.
المسارات المتوازية بلا default.js. صار كل slot يتطلّب ملف default.js
صريحًا، ويفشل البناء بدونه. ملفٌّ يستدعي notFound() أو يُعيد null يستعيد
السلوك السابق.
Node 18. الحدّ الأدنى صار Node 20.9، و TypeScript 5.1. وأهداف المتصفحات انتقلت إلى Chrome و Edge و Firefox بإصدار 111+ و Safari 16.4+.
next lint و AMP وإعدادات وقت التشغيل. كلها أُزيلت. لم يعد
serverRuntimeConfig و publicRuntimeConfig موجودَين - استخدموا متغيّرات
البيئة. وnext/legacy/image مهجور، وكذلك images.domains الذي حلّ محلّه
remotePatterns.
ما يتغيّر بصمت، وهو الجزء الذي يحتاج تخطيطًا
تخزين الصور المؤقّت انتقل من 60 ثانية إلى 4 ساعات. صارت قيمة
images.minimumCacheTTL الافتراضية 14400. لا شيء يرمي خطأً. وإن كنتم
تعتمدون على القيمة القديمة لتحديث صور تتغيّر خلال اليوم، فهي لم تعد تتحدّث -
والعَرَض صورة قديمة لا يستطيع أحد إعادة إنتاجها لأن ذاكرة المتصفح لديه تخالف
ذاكرة المُحسِّن. أعيدوا ضبطها صراحةً إن كنتم تحتاجونها:
// next.config.ts
images: { minimumCacheTTL: 60 },next build لم يعد يشغّل الـ lint. إن كان خطّ التكامل لديكم يعتمد على
البناء لالتقاط أخطاء الـ lint، فقد توقّف عن ذلك بهدوء. كما أن
@next/eslint-plugin-next صار يعتمد flat config افتراضيًا. شغّلوا ESLint أو
Biome كخطوة مستقلة، وتحقّقوا من وجود تلك الخطوة قبل أن تفترضوا أنها تمرّ.
قيم srcset الافتراضية للصور تغيّرت. حُذف 16 من مصفوفة imageSizes
الافتراضية، وتغيّرت قيمة qualities الافتراضية. لا يرمي أيٌّ منهما خطأً،
وكلاهما يغيّر ما يُولَّد، وبالتالي ما يُخزَّن ويُقدَّم.
الصور المحلية مع سلسلة استعلام صارت تحتاج إعدادًا. /photo?v=1 يتطلّب
مدخلًا في images.localPatterns مع search مطابق. هذا يرمي خطأً فعلًا -
لكن على المسارات التي تستخدم النمط فقط، وقد لا تكون هي التي في اختباركم
السريع.
الترتيب الذي ينجح
- اقرأوا الدليل قبل الـ codemod. يوجد في
node_modules/next/dist/docs/ابتداءً من 16.2، مطابقًا للإصدار المثبَّت فعلًا لا لما تتذكّره الإنترنت. - شغّلوا codemod الترقية، ثم codemod واجهات الطلب غير المتزامنة منفصلًا
إن كانت لديكم
paramsأوsearchParamsأوcookies()أوheaders()أوdraftMode()متزامنة من فترة توافق الإصدار 15. فـ codemod الترقية لا يشغّل كل عمليات الترحيل. - احسموا مسألة proxy عن قصد، لأن لا شيء سيسألكم عنها.
- قارنوا مخرجات البناء بالقديمة. أي المسارات
○وأيّهاƒينبغي ألّا يكون قد تغيّر، وإن تغيّر فالأمر يستحق الفهم قبل النشر. - راجعوا القائمة الصامتة أعلاه مقابل إعداداتكم أنتم.
إن كنتم متأخّرين عدّة إصدارات
الخطوة من 15 إلى 16 محتملة. أما القدوم من 13 أو 14 مع Pages Router ما زال في الشجرة فمشروع آخر، والخطأ هو معاملته كترقية واحدة. الترحيل دون تجميد المزايا يشرح الترتيب الذي يُبقي التطبيق قابلًا للنشر أثناء ذلك، و الترحيل والإنقاذ هو هذا العمل ننفّذه نحن.
