المقاييس المخصّصة

تتوفّر قيمة كبيرة في المقاييس التي تركّز على المستخدم والتي يمكنك قياسها على مستوى جميع المواقع الإلكترونية. تتيح لك هذه المقاييس ما يلي:

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

تقدّم المقاييس الشاملة أساسًا جيدًا، ولكن في كثير من الحالات، عليك قياس أكثر من هذه المقاييس من أجل تسجيل التجربة الكاملة لموقعك الإلكتروني.

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

  • هي المدة التي يستغرقها تطبيق الصفحة الواحدة (SPA) للانتقال من "صفحة" إلى أخرى.
  • يشير ذلك إلى المدة التي تستغرقها الصفحة لعرض البيانات التي تم استرجاعها من قاعدة بيانات للمستخدمين الذين سجّلوا الدخول.
  • المدة التي يستغرقها الترطيب في تطبيق يتم عرضه من جهة الخادم (SSR)
  • معدّل نتيجة ذاكرة التخزين المؤقت للموارد التي يتم تحميلها من قِبل الزوّار المتكرّرين
  • تمثّل هذه السمة وقت استجابة اللعبة لأحداث النقر أو أحداث لوحة المفاتيح.

واجهات برمجة التطبيقات لقياس المقاييس المخصّصة

في السابق، لم يكن لدى مطوّري الويب العديد من واجهات برمجة التطبيقات المنخفضة المستوى لقياس الأداء، ونتيجةً لذلك، كان عليهم اللجوء إلى حلول غير تقليدية لمعرفة ما إذا كان الموقع الإلكتروني يعمل بشكل جيد.

على سبيل المثال، يمكن تحديد ما إذا كانت سلسلة التعليمات الرئيسية محظورة بسبب مهام JavaScript التي تستغرق وقتًا طويلاً من خلال تنفيذ حلقة requestAnimationFrame وحساب الفرق بين كل إطار. إذا كانت الدلتا أطول بكثير من عدد اللقطات في الثانية للشاشة، يمكنك الإبلاغ عن ذلك على أنّه مهمة يستغرق تنفيذها وقتًا طويلاً. مع ذلك، لا ننصح باستخدام هذه الحلول لأنّها تؤثّر في الأداء (من خلال استنزاف البطارية، مثلاً).

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

Performance Observer API

Browser Support

  • Chrome: 52.
  • Edge: 79.
  • Firefox: 57.
  • Safari: 11.

Source

واجهة برمجة التطبيقات Performance Observer هي الآلية التي تجمع البيانات وتعرضها من جميع واجهات برمجة التطبيقات الأخرى المتعلّقة بالأداء والموضّحة في هذه الصفحة. ويُعدّ فهمها أمرًا بالغ الأهمية للحصول على بيانات جيدة.

يمكنك استخدام PerformanceObserver للاشتراك بشكل غير مباشر في الأحداث ذات الصلة بالأداء. يتيح ذلك تنشيط عمليات معاودة الاتصال لواجهة برمجة التطبيقات خلال فترات عدم النشاط، ما يعني أنّها لن تتداخل عادةً مع أداء الصفحة.

لإنشاء PerformanceObserver، مرِّر إليها دالة ردّ اتصال سيتم تنفيذها كلّما تم إرسال إدخالات أداء جديدة. بعد ذلك، يمكنك إخبار المراقب بأنواع الإدخالات التي يجب الاستماع إليها باستخدام طريقة observe():

const po = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    // Log the entry and all associated details.
    console.log(entry.toJSON());
  }
});

po.observe({type: 'some-entry-type'});

تدرج الأقسام التالية جميع أنواع الإدخالات المختلفة المتاحة للمراقبة، ولكن في المتصفحات الأحدث، يمكنك فحص أنواع الإدخالات المتاحة من خلال السمة الثابتة PerformanceObserver.supportedEntryTypes.

مراقبة الإدخالات التي حدثت من قبل

بشكلٍ تلقائي، يمكن لـ PerformanceObserver كائنات مراقبة الإدخالات فقط عند حدوثها. يمكن أن يتسبب ذلك في حدوث مشاكل إذا كنت تريد تحميل رمز إحصاءات الأداء بشكل غير متزامن حتى لا يحظر الموارد ذات الأولوية الأعلى.

للحصول على إدخالات سابقة (بعد حدوثها)، اضبط العلامة buffered على true عند طلب observe(). سيتضمّن المتصفّح إدخالات سابقة من مخزن مؤقت لإدخالات الأداء في المرة الأولى التي يتم فيها استدعاء دالة معاودة الاتصال PerformanceObserver، وذلك بما يصل إلى الحد الأقصى لحجم ذاكرة التخزين المؤقت لهذا النوع.

po.observe({
  type: 'some-entry-type',
  buffered: true,
});

واجهات برمجة التطبيقات القديمة المتعلقة بالأداء التي يجب تجنُّبها

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

على الرغم من أنّ هذه الواجهات لا تزال متاحة، لا يُنصح باستخدامها لأنّها لا تتيح لك الاستماع إلى وقت إصدار إدخالات جديدة. بالإضافة إلى ذلك، لا يتم عرض العديد من واجهات برمجة التطبيقات الجديدة (مثل largest-contentful-paint) من خلال العنصر performance، بل يتم عرضها فقط من خلال PerformanceObserver.

ما لم تكن بحاجة إلى التوافق مع Internet Explorer، من الأفضل تجنُّب هذه الطرق في الرمز واستخدام PerformanceObserver من الآن فصاعدًا.

User Timing API

Browser Support

  • Chrome: 28.
  • Edge: 12.
  • Firefox: 38.
  • Safari: 11.

Source

User Timing API هي واجهة برمجة تطبيقات لقياس البيانات للأغراض العامة تُستخدَم في المقاييس المستندة إلى الوقت. تتيح لك هذه السمة وضع علامات بشكل عشوائي في نقاط زمنية، ثم قياس المدة بين تلك العلامات لاحقًا.

// Record the time immediately before running a task.
performance.mark('myTask:start');
await doMyTask();

// Record the time immediately after running a task.
performance.mark('myTask:end');

// Measure the delta between the start and end of the task
performance.measure('myTask', 'myTask:start', 'myTask:end');

في حين أنّ واجهات برمجة التطبيقات، مثل Date.now() أو performance.now()، تمنحك إمكانات مشابهة، فإنّ ميزة استخدام User Timing API هي أنّها تتكامل بشكل جيد مع أدوات الأداء. على سبيل المثال، تعرض "أدوات مطوّري البرامج في Chrome" قياسات User Timing في لوحة "الأداء"، كما أنّ العديد من مقدّمي خدمات الإحصاء يتتبّعون تلقائيًا أي قياسات تجريها ويرسلون بيانات المدة إلى الخلفية الإحصائية.

للإبلاغ عن قياسات "توقيت المستخدم"، يمكنك استخدام PerformanceObserver والتسجيل لمراقبة الإدخالات من النوع measure:

// Create the performance observer.
const po = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    // Log the entry and all associated details.
    console.log(entry.toJSON());
  }
});

// Start listening for `measure` entries to be dispatched.
po.observe({type: 'measure', buffered: true});

Long Tasks API

Browser Support

  • Chrome: 58.
  • Edge: 79.
  • Firefox: not supported.
  • Safari: not supported.

Source

تفيد واجهة برمجة التطبيقات Long Tasks API في معرفة الوقت الذي يتم فيه حظر سلسلة التعليمات الرئيسية للمتصفّح لفترة كافية للتأثير في عدد اللقطات في الثانية أو وقت استجابة الإدخال. ستُبلغ واجهة برمجة التطبيقات عن أي مهام تستغرق تنفيذًا أطول من 50 ملي ثانية.

عندما تحتاج إلى تنفيذ رمز برمجي مكلف أو تحميل نصوص برمجية كبيرة وتنفيذها، من المفيد تتبُّع ما إذا كان هذا الرمز يحظر سلسلة التعليمات الرئيسية. في الواقع، تستند العديد من المقاييس ذات المستوى الأعلى إلى Long Tasks API نفسها (مثل سرعة الاستعداد للتفاعل (TTI) وإجمالي وقت الحظر (TBT)).

لتحديد وقت حدوث المهام الطويلة، يمكنك استخدام PerformanceObserver والتسجيل لمراقبة الإدخالات من النوع longtask:

// Create the performance observer.
const po = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    // Log the entry and all associated details.
    console.log(entry.toJSON());
  }
});

// Start listening for `longtask` entries to be dispatched.
po.observe({type: 'longtask', buffered: true});

Long Animation Frames API

Browser Support

  • Chrome: 123.
  • Edge: 123.
  • Firefox: not supported.
  • Safari: not supported.

Source

Long Animation Frames API هي تكرار جديد لواجهة Long Tasks API التي تنظر إلى اللقطات الطويلة بدلاً من المهام الطويلة التي تزيد مدتها عن 50 ملي ثانية. يعالج ذلك بعض عيوب Long Tasks API، بما في ذلك تحديد المصدر بشكل أفضل ونطاق أوسع من التأخيرات التي قد تسبّب مشاكل.

لتحديد وقت حدوث اللقطات الطويلة، يمكنك استخدام PerformanceObserver والتسجيل لمراقبة الإدخالات من النوع long-animation-frame:

// Create the performance observer.
const po = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    // Log the entry and all associated details.
    console.log(entry.toJSON());
  }
});

// Start listening for `long-animation-frame` entries to be dispatched.
po.observe({type: 'long-animation-frame', buffered: true});

Element Timing API

Browser Support

  • Chrome: 77.
  • Edge: 79.
  • Firefox: not supported.
  • Safari: not supported.

Source

يفيد مقياس سرعة عرض أكبر محتوى مرئي (LCP) في معرفة الوقت الذي تم فيه عرض أكبر صورة أو مقطع نصي على الشاشة، ولكن في بعض الحالات، قد تحتاج إلى قياس الوقت المستغرَق لعرض عنصر مختلف.

في هذه الحالات، استخدِم Element Timing API. تم إنشاء واجهة برمجة التطبيقات LCP API استنادًا إلى واجهة برمجة التطبيقات Element Timing API، وهي تضيف إعداد تقارير تلقائي عن أكبر عنصر مرئي، ولكن يمكنك أيضًا إعداد تقارير عن عناصر أخرى من خلال إضافة السمة elementtiming إليها بشكلٍ صريح، وتسجيل PerformanceObserver لمراقبة نوع الإدخال element.

<img elementtiming="hero-image" />
<p elementtiming="important-paragraph">This is text I care about.</p>
<!-- ... -->

<script>
  const po = new PerformanceObserver((entryList) => {
    for (const entry of entryList.getEntries()) {
      // Log the entry and all associated details.
      console.log(entry.toJSON());
    }
  });

  // Start listening for `element` entries to be dispatched.
  po.observe({type: 'element', buffered: true});
</script>

Event Timing API

Browser Support

  • Chrome: 76.
  • Edge: 79.
  • Firefox: 89.
  • Safari: 26.2.

Source

يقيس مقياس مدى استجابة الصفحة لتفاعلات المستخدم (INP) مدى استجابة الصفحة بشكل عام من خلال رصد جميع التفاعلات المتعلقة بالنقر والضغط على لوحة المفاتيح طوال فترة بقاء الصفحة نشطة. في معظم الأحيان، يكون مقياس INP للصفحة هو التفاعل الذي استغرق أطول وقت لإكماله، بدءًا من الوقت الذي بدأ فيه المستخدم التفاعل، وحتى الوقت الذي يعرض فيه المتصفّح اللقطة التالية التي تعرض النتيجة المرئية لبيانات المستخدم.

يتوفّر مقياس INP بفضل واجهة برمجة التطبيقات Event Timing API. تعرض واجهة برمجة التطبيقات هذه عددًا من الطوابع الزمنية التي تحدث خلال دورة حياة الحدث، بما في ذلك:

  • startTime: الوقت الذي يتلقّى فيه المتصفّح الحدث.
  • processingStart: الوقت الذي يمكن فيه للمتصفّح بدء معالجة معالِجات الأحداث للحدث.
  • processingEnd: الوقت الذي ينتهي فيه المتصفّح من تنفيذ كل الرموز المتزامنة التي تمّت بدؤها من معالجات الأحداث لهذا الحدث.
  • duration: الوقت (يتم تقريبه إلى 8 مللي ثانية لأسباب أمنية) بين الوقت الذي يتلقّى فيه المتصفّح الحدث إلى أن يتمكّن من عرض الإطار التالي بعد الانتهاء من تنفيذ كل الرموز المتزامنة التي تم بدء تشغيلها من معالجات الأحداث.

يوضّح المثال التالي كيفية استخدام هذه القيم لإنشاء قياسات مخصّصة:

const po = new PerformanceObserver((entryList) => {
  // Get the last interaction observed:
  const entries = Array.from(entryList.getEntries()).forEach((entry) => {
    // Get various bits of interaction data:
    const inputDelay = entry.processingStart - entry.startTime;
    const processingTime = entry.processingEnd - entry.processingStart;
    const presentationDelay = entry.startTime + entry.duration - entry.processingEnd;
    const duration = entry.duration;
    const eventType = entry.name;
    const target = entry.target || "(not set)"

    console.log("----- INTERACTION -----");
    console.log(`Input delay (ms): ${inputDelay}`);
    console.log(`Event handler processing time (ms): ${processingTime}`);
    console.log(`Presentation delay (ms): ${presentationDelay}`);
    console.log(`Total event duration (ms): ${duration}`);
    console.log(`Event type: ${eventType}`);
    console.log(target);
  });
});

// A durationThreshold of 16ms is necessary to include more
// interactions, since the default is 104ms. The minimum
// durationThreshold is 16ms.
po.observe({type: 'event', buffered: true, durationThreshold: 16});

Resource Timing API

Browser Support

  • Chrome: 29.
  • Edge: 12.
  • Firefox: 35.
  • Safari: 11.

Source

تمنح Resource Timing API المطوّرين إحصاءات تفصيلية حول كيفية تحميل موارد صفحة معيّنة. على الرغم من اسم واجهة برمجة التطبيقات، لا تقتصر المعلومات التي تقدّمها على بيانات التوقيت فقط (مع أنّ هناك الكثير من هذه البيانات). تشمل البيانات الأخرى التي يمكنك الوصول إليها ما يلي:

  • initiatorType: طريقة جلب المرجع، مثلاً من علامة <script> أو <link> أو من طلب fetch()
  • nextHopProtocol: البروتوكول المستخدَم لاسترجاع المورد، مثل h2 أو quic
  • encodedBodySize/decodedBodySize]: حجم المورد في شكله المرمّز أو غير المرمّز (على التوالي)
  • transferSize: حجم المورد الذي تم نقله فعليًا عبر الشبكة. عندما يتم توفير الموارد من ذاكرة التخزين المؤقت، يمكن أن تكون هذه القيمة أصغر بكثير من encodedBodySize، وفي بعض الحالات يمكن أن تكون صفرًا (إذا لم يكن من المطلوب إعادة التحقّق من صحة ذاكرة التخزين المؤقت).

يمكنك استخدام السمة transferSize لإدخالات توقيت الموارد من أجل قياس مقياس معدّل الوصول إلى ذاكرة التخزين المؤقت أو مقياس إجمالي حجم الموارد المخزّنة مؤقتًا، ما قد يكون مفيدًا في فهم كيفية تأثير استراتيجية تخزين الموارد مؤقتًا في الأداء بالنسبة إلى الزوّار المتكرّرين.

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

// Create the performance observer.
const po = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    // If transferSize is 0, the resource was fulfilled using the cache.
    console.log(entry.name, entry.transferSize === 0);
  }
});

// Start listening for `resource` entries to be dispatched.
po.observe({type: 'resource', buffered: true});

Browser Support

  • Chrome: 57.
  • Edge: 12.
  • Firefox: 58.
  • Safari: 15.

Source

تشبه Navigation Timing API واجهة Resource Timing API، ولكنّها تعرض فقط طلبات التنقّل. يشبه نوع الإدخال navigation أيضًا نوع الإدخال resource، ولكنّه يتضمّن بعض المعلومات الإضافية الخاصة بطلبات التنقّل فقط (مثلما يحدث عند تشغيل الحدثين DOMContentLoaded وload).

يتوفّر أحد المقاييس التي يتتبّعها العديد من المطوّرين لفهم مدة استجابة الخادم (مدة تحميل أول بايت (TTFB)) باستخدام Navigation Timing API، وتحديدًا الطابع الزمني responseStart للإدخال.

// Create the performance observer.
const po = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    // If transferSize is 0, the resource was fulfilled using the cache.
    console.log('Time to first byte', entry.responseStart);
  }
});

// Start listening for `navigation` entries to be dispatched.
po.observe({type: 'navigation', buffered: true});

هناك مقياس آخر قد يهمّ المطوّرين الذين يستخدمون مشغّل الخدمات، وهو وقت بدء تشغيل مشغّل الخدمات لطلبات التنقّل. هذا هو مقدار الوقت الذي يستغرقه المتصفّح لبدء سلسلة التعليمات البرمجية الخاصة ببرنامج عامل الخدمة قبل أن يتمكّن من بدء اعتراض أحداث الجلب.

يمكن تحديد وقت بدء تشغيل عامل الخدمة لطلب انتقال معيّن من الفرق بين entry.responseStart وentry.workerStart.

// Create the performance observer.
const po = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    console.log('Service Worker startup time:',
        entry.responseStart - entry.workerStart);
  }
});

// Start listening for `navigation` entries to be dispatched.
po.observe({type: 'navigation', buffered: true});

Server Timing API

Browser Support

  • Chrome: 65.
  • Edge: 79.
  • Firefox: 61.
  • Safari: 16.4.

Source

تتيح لك Server Timing API تمرير بيانات التوقيت الخاصة بالطلبات من الخادم إلى المتصفّح من خلال عناوين الاستجابة. على سبيل المثال، يمكنك توضيح المدة التي استغرقتها عملية البحث عن البيانات في قاعدة بيانات لطلب معيّن، وهو ما يمكن أن يكون مفيدًا في تصحيح أخطاء مشاكل الأداء الناتجة عن البطء على الخادم.

بالنسبة إلى المطوّرين الذين يستخدمون مزوّدي خدمات إحصاءات تابعين لجهات خارجية، فإنّ Server Timing API هي الطريقة الوحيدة لربط بيانات أداء الخادم بمقاييس الأداء الأخرى التي قد تقيسها أدوات الإحصاءات هذه.

لتحديد بيانات توقيت الخادم في ردودك، يمكنك استخدام عنوان الاستجابة Server-Timing. إليك مثالاً.

HTTP/1.1 200 OK

Server-Timing: miss, db;dur=53, app;dur=47.2

بعد ذلك، يمكنك قراءة هذه البيانات من صفحاتك في كل من إدخالات resource أو navigation من واجهتَي برمجة التطبيقات Resource Timing وNavigation Timing.

// Create the performance observer.
const po = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    // Logs all server timing data for this response
    console.log('Server Timing', entry.serverTiming);
  }
});

// Start listening for `navigation` entries to be dispatched.
po.observe({type: 'navigation', buffered: true});