قياس الأداء في تطبيقات Next.js

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

تتيح لك الأداة Next.js Analytics تحليل وقياس أداء الصفحات مستخدمًا مؤشرات مختلفة. فقد تبدأ بتجميع نقاط التجربة الواقعية Real Experience Score دون إعدادات عند النشر على Vercel، كما يمكنك دعم Next.js Analytics إن اخترت الاستضافة الذاتية.

تشرح الأقسام التالية في هذه الصفحة من التوثيق الطبقات المدمجة التي يستخدمها Next.js Analytics.

استخدام المؤشرات التي تناسبك

عليك إولًا إنشاء مكوّن App مخصص وتعرّف داخله الدالة reportWebVitals:

// pages/_app.js
export function reportWebVitals(metric) {
  console.log(metric)
}

function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />
}

export default MyApp

تُستدعى هذه الدالة عندما تُحسب القيمة النهائية لأي مؤشر في الصفحة، وبإمكانك عندها عرض النتيجة على الطرفية إو إرسالها إلى وصلة خاصة لتخزينها. يتكوّن الكائن metric الذي يُعاد إلى الدالة من خاصيات عدة هي:

  • id: مُعرِّف فريد للمؤشر في سياق الحمل الذي تعرضه الصفحة الحالية.
  • name: اسم المؤشر.
  • startTime: زمن التسجيل الأول لقيمة الأداء بالميلي ثانية إن أمكن.
  • value: قيمة أو فترة زمنية لمؤشر الأداء.
  • label: نوع المؤشر web-vital (مؤشرات ويب الحيوية) أو custom (مؤشر مخصص)

مؤشرات الويب الحيوية Web Vitals

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


بإمكانك التعامل مع جميع المؤشرات السابقة من خلال العنوان web-vital للكائن metric:

export function reportWebVitals(metric) {
  if (metric.label === 'web-vital') {
    console.log(metric) // تُعرض المؤشرات التالية 
                        // ({ id, name, startTime, value, label })
                        // على الطرفية
  }
}

وهنالك أيضًا خيارات لمعالجة كل مؤشر على حدى:

export function reportWebVitals(metric) {
  switch (metric.name) {
    case 'FCP':
      // FCP يعالج نتيجة
      break
    case 'LCP':
      // LCP يعالج نتيجة
      break
    case 'CLS':
      // CLS يعالج نتيجة
      break
    case 'FID':
      // FID يعالج نتيجة
      break
    case 'TTFB':
      // TTFB يعالج نتيجة
      break
    default:
      break
  }
}

تستخدم المكتبة web-vitals التي يؤمنها طرف آخر لقياس هذه المؤشرات. وتعتمد توافقية المتصفح على المؤشر الذي يقيسه، لذلك عليك الاطلاع على المتصفحات التي تدعمها هذه الأداة.

المؤشرات المخصصة Custom metrics

إضافة إلى المؤشرات الحيوية السابقة، ستجد بعض المؤشرات المخصصة التي تقيس الزمن الذي تستغرقه الصفحة لكي تُرطَّب وتصيَّر:

  • Next.js-hydration: الفترة الزمنية التي تستغرقها صفحة بين بداية ونهاية الترطيب (بالميلي ثانية).
  • Next.js-route-change-to-render: الفترة الزمنية التي تستغرقها صفحة ليبدأ تصييرها بعد تغيّر الوجهة (أو المسار).
  • Next.js-render: الفترة الزمنية التي تستغرقها صفحة لينتهي تصييرها بعد تغيّر الوجهة (أو المسار).

بإمكانك التعامل مع جميع نتائج هذه المؤشرات باستخدام العنوان custom للكائن metric:

export function reportWebVitals(metric) {
  if (metric.label === 'custom') {
    console.log(metric) // تُعرض المؤشرات التالية 
                        // ({ id, name, startTime, value, label })
                        // على الطرفية
  }
}

وهنالك أيضًا خيار لمعالجة كل مؤشر على حدى:

export function reportWebVitals(metric) {
  switch (metric.name) {
    case 'Next.js-hydration':
      // تعالج نتيجة الترطيب
      break
    case 'Next.js-route-change-to-render':
      // تعالج نتيجة زمن انتهاء التصيير عند تغير الوجهة
      break
    case 'Next.js-render':
      // تعالج زمن بداية التصيير عند تغير الوجهة
      break
    default:
      break
  }
}

تعمل هذه المؤشرات في جميع المتصفحات التي تدعم الواجهة البرمجية User Timing.

إرسال البيانات إلى الأداة analytics

بإمكانك إرسال بيانات أي مؤشر إلى الوصلة الخاصة بالأداة analytics لقياس وتتبع الأداء الفعلي للمستخدم على موقعك من خلال دالة توصيل. إليك مثالًا:

export function reportWebVitals(metric) {
  const body = JSON.stringify(metric)
  const url = 'https://example.com/analytics'
  
  //إن كان متاحًا `navigator.sendBeacon()` استخدم 
  //`fetch()` وإلا تراجع إلى 
  if (navigator.sendBeacon) {
    navigator.sendBeacon(url, body)
  } else {
    fetch(url, { body, method: 'POST', keepalive: true })
  }
}

ملاحظة: إن كنت تستخدم Google Analytics، فستسمح لك قيمة id أن تبني توزعًا يدويًا للمؤشرات لتحسب نسبًا مئوية وغيرها إن شئت.

export function reportWebVitals({ id, name, label, value }) {
// كما في المثال التالي Google Analytics إن هيأت `window.gtag` استخدم 
// https://github.com/vercel/next.js/blob/canary/examples/with-google-analytics/pages/_app.js
window.gtag('event', name, {
 event_category:
   label === 'web-vital' ? 'Web Vitals' : 'Next.js custom metric',
 value: Math.round(name === 'CLS' ? value * 1000 : value), // يجب أن تكون القيم صحيحة
 event_label: id, //فريد بالنسبة للحمل الحالي للصفحة id المعرف
 non_interaction: true, //bounce rate تحاشى التاثير على معدل النشاط 
})
}

للمزيد، انظر هذه الصفحة.

استكشاف ما يؤثر على مؤشرات الويب الحيوية

عند استكشاف المشاكل المتعلقة بمؤشرات الويب الحيوية وفحصها، قد نحتاج عادةً إلى أي معلومة تفيدنا في تحديد سبب المشكلة مثلًا قد نحتاج في مؤشر انزياح الهيكل التراكمي CLS إلى معرفة أول عنصر منزاح عندما حصلت مشكلة الانزياح الهيكل أو مثلًا قد نحتاج في مؤشر أضخم محتوى مرئي LCP إلى تحديد العنصر المسؤول عن خلل هذا المؤشر فإن كان العنصر صورةٌ فسيساعدنا معرفة تفاصيله ورابط الصورة تلك إلى تحديد الصورة بالضبط والرجوع إليها وتحسينها.

تعرف عملية تحديد المساهم الأكبر في مشاكل الويب الحيوية باسم "الإرجاع" attribution أي إرجاع المشكلة إلى مسببها، وتساعدنا هذه العملية في معرفة تفاصيل أوسع وأدق عن المشكلة مثل:

هذه العملية معطلة افتراضيًا في Next.js ويمكنك تفعيلها لكل مؤشر من ملف next.config.js بالشكل التالي:

// next.config.js
experimental: {
  webVitalsAttribution: ['CLS', 'LCP']
}

القيم الصالحة لتمريرها إلى webVitalsAttribution هي كل مؤشرات الويب الحيوية web-vitals المحددة في النوع NextWebVitalsMetric.

استخدام TypeScript

يمكنك استخدام النوع المدمج NextWebVitalsMetric في حال استخدمت TypeScript:

// pages/_app.tsx

import type { AppProps, NextWebVitalsMetric } from 'next/app'

function MyApp({ Component, pageProps }: AppProps) {
  return <Component {...pageProps} />
}

export function reportWebVitals(metric: NextWebVitalsMetric) {
  console.log(metric)
}

export default MyApp

المصادر