ما قبل مرحلة الإنتاج في Next.js

من موسوعة حسوب

إليك بعض النصائح المهمة لتضمن أفضل تجربة مستخدم عندما تصل بتطبيق Next.js إلى مرحلة الإنتاج.

نصائح عامة

  • استخدم التخزين المؤقت caching أينما أتيح لك ذلك.
  • تأكد من أن قواعد البيانات والواجهة الخلفية لتطبيقك من نفس الأصل (انشرهما ضمن نفس الموقع).
  • حاول أن تشحن أقل كمية ممكنة من شيفرة JavaScript.
  • أخِّر تحميل تجميعات JavaScript كبيرة الحجم حتى تحتاجها.
  • تأكد من إعداد آلية للعمل مع السجلات logging.
  • تأكد من إعداد آلية لمعالجة الأخطاء error handling.
  • هيئ صفحات للحالة 404 (غير موجود) وللحالة 500 (خطأ).
  • تأكد من قياسك لأداء التطبيق.
  • استخدم الأداة Lighthouse للتحقق من الأداء وتطبيقك لأفضل الممارسات وشمولية الوصول وتطبيقك لمعايير تحسين محركات البحث SEO. للحصول على أفضل النتائج، استخدم نسخة الإنتاج في متصفحك في نمط التخفي incognito كي لا تتأثر النتائج بالإضافات extensions المثبتة ضمن المتصفح.
  • راجع صفحة المتصفحات والميزات المدعومة من توثيق Next.js.
  • حسِّن الأداء من خلال استخدام:
  • حسن أداء التطبيق من ناحية التحميل.

التخزين المؤقت Caching

يُحسّن التخزين المؤقت للبيانات زمن الاستجابة ويقلل عدد الطلبات المرسلة إلى خدمات خارجية. تضيف Next.js تلقائيًا ترويسة التخزين المؤقت caching header إلى الأصول assets التي لا تتغير في المجلد next/static_/ مثل ملفات JavaScript و CSS والصور الساكنة وغيرها من الوسائط.

Cache-Control: public, max-age=31536000, immutable

ستُبدَّل قيمة الترويسة Cache-Control إن ضبطت في الملف next.config.js في مرحلة الإنتاج للتأكد من إمكانية التخزين المؤقت للأصول الساكنة بفعالية وأفضل ما يمكن آنذاك. فإن أردت إعادة التحقق من البيانات المخزنة مؤقتًا لصفحة ولّدت بشكل ساكن، اضبط قيمة الخاصية revalidate في الدالة getStaticProps الخاصة بهذه الصفحة. وإن كنت تستخدم المكوّن next/image فهنالك بعض القواعد الخاصة بالتخزين المؤقت لمحمَّل الصور المحسَّنة. ملاحظة: عندما تشغّل تطبيقك محليًا بتنفيذ الأمر next dev تُلغى الترويسات لمنع التخزين المؤقت على الحاسوب في مرحلة التطوير.

Cache-Control: no-cache, no-store, max-age=0, must-revalidate

بإمكانك أيضًا استخدام ترويسات التخزين المؤقت ضمن الدالة getServerSideProps ومسارات API للاستجابة الديناميكية. إليك مثالًا عن استخدام الخاصية stale-while-revalidate:

// (s-maxage=10)تُعد هذه القيمة جديدة مدة عشر ثوان.
// إن أعيد الطلب ضمن هذه الثواني العشرة ستبقى هذه القيمة حديثة
// بينما إن أعيد الطلب قبل 59 ثانية ستُصيّر القيمة على الرغم من كونها قديمة
//(stale-while-revalidate=59).
//سيجري طلب خلف الستار لتحديث  هذه القيمة في الذاكرة المؤقتة 
//سترى هذه القيمة الجديدة إن حدّثت الصفحة
export async function getServerSideProps({ req, res }) {
  res.setHeader(
    'Cache-Control',
    'public, s-maxage=10, stale-while-revalidate=59'
  )

  return {
    props: {},
  }
}

تُضبط الترويسات Cache-Control افتراضيًا بشكل مختلف وفقًا لطريقة إحضار البيانات في الصفحة.

  • تأخذ الترويسة Cache-Control القيمة الافتراضية التي يضبطها الأمر next start إن استخدمت صفحة إحدى الدالتين getServerSideProps أو getInitialProps لكي تمنع التخزين المؤقت العَرضي للاستجابة التي لا يمكن تخزينها مؤقتًا. إن أردت استخدام أسلوب آخر للتخزين المؤقت مع الدالة يمكنك استخدام التابع التالي داخل هذه الدالة:
res.setHeader('Cache-Control', 'value_you_prefer')
  • إن استخدمت الصفحة الدالة getStaticProps ستمتلك الترويسة Cache-Control الصيغة التالية لتخزين البيانات مؤقتًا أطول فترة ممكنة:
// revalidate إن ضُبطت قيمة 
s-maxage=REVALIDATE_SECONDS, stale-while-revalidate
// revalidate أو إن لم تُستخدم
s-maxage=31536000, stale-while-revalidate

ملاحظة: لا بدّ أن يدعم مزوّد الاستضافة التخزين المؤقت للاستجابة الديناميكة. فإن كنت تستضيف تطبيقك بنفسك، فعليك أن تضيف المنطق السابق بنفسك من خلال التخزين بتقنية مفتاح/قيمة مثل Redis. كما سيساعدك Edge Caching دون أية إعدادات إن كنت تستخدم Vercel.

تخفيض حجم JavaScript

لتقليل حجم شيفرة JavaScript المرسلة إلى المتصفح، تستطيع استخدام الأدوات التالية لفهم محتويات كل تجميع من تجميعات JavaScript:

  • Import Cost: تعرض حجم الحزمة المدرجة ضمن الشيفرة في بيئة VSCode (فيجوال ستدوديو كود).
  • Package Phobia: يحسب تبعات إضافة اعتمادية تطوير جديدة إلى مشروعك.
  • Bundle Phobia: يحلل مقدار الزيادة التي تسببها اعتمادية في حجم التجميعات.
  • Webpack Bundle Analyzer: يعرض حجم ملف الخرج لحزمة webpack بأسلوب بصري تفاعلي على شكل خريطة شجرية قابلة للتكبير.
  • bundlejs: أداة متاحة عبر الإنترنت لتحزيم bundle وتقليص minify مشاريعك.

تُفصل شيفرة JavaScript لكل ملف موجود في المجلد /pages تلقائيًا ضمن تجميعة خاصة عند بناء التطبيق next build. بإمكانك أيضًا استخدام الإدراج الديناميكي لإبطاء تحميل المكوّنات والمكتبات، إذ قد ترغب مثلًا في تأخير تحميل شيفرة وحدة برمجية حتى ينقر المستخدم على زر مثلًا.

إدارة السجلات Logging

تعمل Next.js على جانبي الخادم والعميل وبالتالي ستجد عدة نماذج لدعم إدارة السجلات والرسائل:

  • console.log من جانب المتصفح.
  • stdout من جانب الخادم.

لكن إن أردت استخدام حزمة مُهيكلة لإدارة السجلات سننصحك بالحزمة Pino، وإن كنت تعمل على Vercel، فهناك حزمة متكاملة مدمجة لإدارة السجلات تتوافق مع Next.js.

التعامل مع الأخطاء

بإمكانك عند وقوع خطأ غير متوقع أثناء تنفيذ الشيفرة التحكم بطريقة عرضه للمستخدم باستخدام الصفحة "500". ويُفضّل أن تخصص هذه الصفحة بما يلائم تطبيقك بدلًا من صفحة Next.js الافتراضية. كما يمكنك تتبع وتسجيل الاستثناءات والأخطاء من خلال أدوات مثل Sentry.

يوضح لك هذا المثال كيفية إلتقاط الأخطاء والتبليغ عنها من طرف المتصفح ومن طرف الخادم باستعمال Sentry SDK المتاحة من أجل تطبيقات Next.js، كما هنالك دمج Sentry مع Vercel.

أداء التطبيق أثناء التحميل

لا بد أولًا كي تحسن أداء التطبيق أثناء التحميل من تحديد ما ينبغي قياسه وكيفية قياسه، وتُعد مؤشرات ويب الحيوية Core Web Vitals معيارًا جيدًا يمكن قياسه من خلال المتصفح. إن لم تكن على دراية بحيثيات هذه المؤشرات، بإمكانك البحث عنها عبر الإنترنت واختيار المؤشرات المحددة التي تناسبك في تحديد أداء التحميل لتطبيق.

وقد ترغب (كعمل نموذجي) في قياس أداء التحميل في البيئات التالية:

  • في المختبر من خلال حاسوبك الشخصي أو المحاكي.
  • في حقل العمل باستخدام بيانات حقيقية لزوار فعليين.
  • محليًا من خلال اختبار تنفّذه على جهازك.
  • عن بعد من خلال اختبار تجريه على حساب سحابي.

كرر استعمال الاستراتيجيات التالية بمجرد أن تنتهي من اختبار أداء التحميل، طبق استراتيجية ثم قس الأداء وحاول أن تحسِّن في التطبيق قدر المستطاع ثم انتقل إلى الأخرى:

  • استخدم التخزين المؤقت في الأماكن القريبة من مكان نشر قاعدة البيانات أو الواجهة البرمجية API.
  • استخدم القيمة التي لن تزيد الحمولة على الواجهة الخلفية للتطبيق.
  • استخدم التجديد التدريجي الساكن للتقليل من عدد الطلبات التي ترسلها إلى الواجهة الخلفية.
  • أزل شيفرة JavaScript غير المستخدمة.

يمكن أن تعطيك بعض مؤشرات ويب الحيوية فكرة عن مدى تأثير حجم التجميعات والاستراتيجيات التي تخفف من هذه التأثيرات مثل:

  • ضبط إعدادات محرر الشيفرة لديك ليعرض تبعات إدراج الاعتماديات وأحجامها.
  • الحصول على حزم بديلة أصغر.
  • التحميل الديناميكي للمكوّنات والاعتماديات.

أمثلة

المصادر