معیارهای سفارشی

داشتن معیارهای جهانی و کاربر محور که می توانید در هر وب سایتی اندازه گیری کنید، می تواند در درک نحوه تجربه کاربران شما از وب و مقایسه سایت شما با رقبا بسیار مفید باشد. با این حال، در بسیاری از موارد، شما نیاز به اندازه گیری بیشتر از معیارهای جهانی دارید تا تجربه کاملی را برای سایت خاص خود به دست آورید.

معیارهای سفارشی به شما امکان می دهد جنبه هایی از تجربه سایت خود را که ممکن است فقط برای سایت شما اعمال شود، اندازه گیری کنید، مانند:

  • چه مدت طول می کشد تا یک برنامه تک صفحه ای (SPA) از یک صفحه به صفحه دیگر منتقل شود.
  • چقدر طول می کشد تا یک صفحه داده های واکشی شده از پایگاه داده را برای کاربرانی که وارد سیستم شده اند نمایش دهد.
  • چه مدت طول می کشد تا یک برنامه رندر شده از سمت سرور (SSR) هیدراته شود.
  • نرخ ضربه حافظه پنهان برای منابع بارگیری شده توسط بازدیدکنندگان بازگشتی.
  • تأخیر رویداد رویدادهای کلیک یا صفحه کلید در یک بازی.

API برای اندازه گیری معیارهای سفارشی

توسعه‌دهندگان وب در طول تاریخ، APIهای سطح پایین زیادی برای اندازه‌گیری عملکرد نداشته‌اند، و در نتیجه، مجبور بوده‌اند برای سنجش عملکرد خوب یک سایت به هک متوسل شوند. برای مثال، می‌توانید با اجرای یک حلقه requestAnimationFrame و محاسبه دلتا بین هر فریم، تعیین کنید که آیا رشته اصلی توسط وظایف طولانی‌مدت جاوا اسکریپت مسدود شده است یا خیر. اگر دلتا به طور قابل توجهی طولانی تر از نرخ فریم نمایشگر باشد، می توانید آن را به عنوان یک کار طولانی گزارش دهید.

با این حال، هک هایی مانند این می توانند بر عملکرد سایت شما تأثیر بگذارند، به عنوان مثال با تخلیه باتری دستگاه. اگر تکنیک‌های اندازه‌گیری عملکرد شما خود باعث مشکلات عملکردی می‌شوند، داده‌هایی که از آنها دریافت می‌کنید دقیق نخواهند بود. بنابراین، توصیه می کنیم از یکی از API های زیر برای ایجاد معیارهای سفارشی استفاده کنید.

Performance Observer API

پشتیبانی مرورگر

  • 52
  • 79
  • 57
  • 11

منبع

Performance Observer API مکانیزمی است که داده ها را از سایر APIهای عملکردی که در این صفحه مورد بحث قرار گرفته اند جمع آوری و نمایش می دهد. درک آن برای به دست آوردن داده های خوب بسیار مهم است.

می‌توانید از PerformanceObserver برای اشتراک غیرفعال رویدادهای مرتبط با عملکرد استفاده کنید. این به تماس‌های API اجازه می‌دهد در دوره‌های بی‌کار فعال شوند، به این معنی که معمولاً در عملکرد صفحه تداخلی ایجاد نمی‌کنند.

هنگام ایجاد یک PerformanceObserver ، یک تماس برگشتی برای آن ارسال کنید که هر زمان که ورودی های عملکرد جدیدی ارسال می شود اجرا می شود. سپس از متد observe() استفاده کنید تا به ناظر بگویید که چه نوع ورودی هایی را به شرح زیر گوش دهد:

// Catch errors that some browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
  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'});
} catch (e) {
  // Do nothing if the browser doesn't support this API.
}

بخش‌های زیر تمام انواع ورودی‌هایی را که می‌توانید مشاهده کنید فهرست می‌کند. در مرورگرهای جدیدتر، می‌توانید با استفاده از ویژگی Static PerformanceObserver.supportedEntryTypes ، انواع ورودی‌های موجود را نیز بررسی کنید.

ورودی هایی را که قبلاً اتفاق افتاده را مشاهده کنید

به‌طور پیش‌فرض، اشیاء PerformanceObserver فقط می‌توانند ورودی‌ها را در زمان وقوع مشاهده کنند. اگر بخواهید کد تجزیه و تحلیل عملکرد خود را با تنبلی بارگیری کنید تا منابع با اولویت بالاتر را مسدود نکند، می تواند باعث ایجاد مشکل شود.

برای دریافت ورودی های تاریخی، observe با پرچم buffered روی true فراخوانی کنید. سپس مرورگر ورودی های تاریخی را از بافر ورود عملکرد خود در اولین باری که PerformanceObserver شما فراخوانی می شود، شامل می شود.

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

APIهای عملکرد قدیمی که باید از آنها اجتناب کنید

قبل از Performance Observer API، توسعه‌دهندگان می‌توانستند به ورودی‌های عملکرد با استفاده از روش‌های زیر تعریف شده روی شی performance دسترسی داشته باشند. ما استفاده از آنها را توصیه نمی کنیم زیرا آنها به شما اجازه نمی دهند به ورودی های جدید گوش دهید.

علاوه بر این، بسیاری از APIهای جدید (مانند وظایف طولانی) توسط شی performance نمایش داده نمی شوند، فقط توسط PerformanceObserver . بنابراین، مگر اینکه به طور خاص به سازگاری با اینترنت اکسپلورر نیاز داشته باشید، بهتر است از این روش ها در کد خود اجتناب کنید و در آینده از PerformanceObserver استفاده کنید.

API زمان‌بندی کاربر

User Timing API یک 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');

اگرچه API هایی مانند Date.now() یا performance.now() توانایی های مشابهی را به شما می دهند، User Timing API بهتر با ابزار عملکرد یکپارچه می شود. به عنوان مثال، Chrome DevTools اندازه‌گیری‌های زمان‌بندی کاربر را در پانل عملکرد تصویری می‌کند و بسیاری از ارائه‌دهندگان تجزیه و تحلیل به‌طور خودکار هر اندازه‌گیری را که انجام می‌دهید ردیابی می‌کنند و داده‌های مدت زمان را به باطن تجزیه و تحلیل خود ارسال می‌کنند.

برای گزارش اندازه‌گیری‌های زمان‌بندی کاربر، یک PerformanceObserver را برای مشاهده ورودی‌های نوع measure ثبت کنید:

// Catch errors some browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
  // 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.
  po.observe({type: 'measure', buffered: true});
} catch (e) {
  // Do nothing if the browser doesn't support this API.
}

Long Tasks API

پشتیبانی مرورگر

  • 58
  • 79
  • ایکس
  • ایکس

منبع

Long Tasks API برای تعیین اینکه چه زمانی رشته اصلی مرورگر به اندازه کافی مسدود شده است تا بر نرخ فریم یا تأخیر ورودی تأثیر بگذارد مفید است. API هر کاری را که بیش از 50 میلی ثانیه اجرا می شود گزارش می دهد.

هر زمان که نیاز به اجرای کدهای گران قیمت یا بارگیری و اجرای اسکریپت های بزرگ دارید، ردیابی اینکه آیا آن کد رشته اصلی را مسدود می کند مفید است. در واقع، بسیاری از معیارهای سطح بالاتر بر روی خود Long Tasks API ساخته شده اند (مانند Time to Interactive (TTI) و Total Blocking Time (TBT) ).

برای تعیین زمان انجام کارهای طولانی، یک PerformanceObserver را برای مشاهده ورودی‌های نوع longtask ثبت کنید:

// Catch errors since some browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
  // 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});
} catch (e) {
  // Do nothing if the browser doesn't support this API.
}

Element Timing API

پشتیبانی مرورگر

  • 77
  • 79
  • ایکس
  • ایکس

منبع

متریک Largest Contentful Paint (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>
// Catch errors since some browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
  // Create the performance observer.
  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});
} catch (e) {
  // Do nothing if the browser doesn't support this API.
}
</script>

API زمان‌بندی رویداد

متریک Interaction to Next Paint (INP) پاسخگویی کلی صفحه را با مشاهده تمام تعاملات کلیک، ضربه و صفحه کلید در طول عمر یک صفحه ارزیابی می کند. INP یک صفحه معمولاً تعاملی است که از زمانی که کاربر تعامل را آغاز کرد تا زمانی که مرورگر فریم بعدی را نشان می‌دهد که نتیجه بصری ورودی کاربر را نشان می‌دهد، طولانی‌ترین زمان را برای تکمیل آن به طول انجامید.

معیار INP توسط API زمان‌بندی رویداد ممکن شده است. این API تعدادی مُهر زمانی را که در طول چرخه حیات رویداد رخ می‌دهند، نشان می‌دهد، از جمله:

  • startTime : زمانی که مرورگر رویداد را دریافت می کند.
  • processingStart : زمانی که مرورگر می‌تواند پردازشگرهای رویداد را برای رویداد شروع کند.
  • processingEnd : زمانی که مرورگر اجرای تمام کدهای همزمان آغاز شده از کنترل کننده رویداد برای این رویداد را به پایان می رساند.
  • duration : زمان (به دلایل امنیتی به 8 میلی ثانیه گرد شده است) بین زمانی که مرورگر رویداد را دریافت می کند تا زمانی که بتواند فریم بعدی را پس از اتمام اجرای تمام کدهای همزمان آغاز شده از کنترل کننده رویداد نقاشی کند.

می توان از این مهرهای زمانی برای اندازه گیری بخش های مجزا از هر تعامل ایجاد شده با یک صفحه یا حتی تعاملات خاصی که ممکن است برای کاربران شما ارزش بالایی داشته باشد، استفاده کرد.

قطعه کد زیر نشان می دهد که چگونه می توانید بیت های مختلفی از داده های مفید را برای هر تعاملی که در صفحه رخ می دهد دریافت کنید:

// Catch errors some browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
  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 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 time (ms): ${processingTime}`);
      console.log(`Total event duration (ms): ${duration}`);
      console.log(`Event type: ${eventType}`);
      console.log(target);
    });
  });

  // A durationThreshold of 16ms is necessary to surface more
  // interactions, since the default is 104ms. The minimum
  // durationThreshold is 16ms.
  po.observe({type: 'event', buffered: true, durationThreshold: 16});
} catch (error) {
  // Do nothing if the browser doesn't support this API.
}

Resource Timeming API

Resource Timing API به توسعه دهندگان بینش دقیقی درباره نحوه بارگیری منابع برای یک صفحه خاص می دهد. با وجود نام API، اطلاعاتی که ارائه می دهد فقط به داده های زمان بندی محدود نمی شود (اگرچه تعداد زیادی از آن وجود دارد). سایر داده هایی که می توانید به آنها دسترسی داشته باشید عبارتند از:

  • initiatorType : چگونه منبع واکشی شده است، مانند تگ <script> یا <link> ، یا از fetch() .
  • nextHopProtocol : پروتکل مورد استفاده برای واکشی منبع، مانند h2 یا quic .
  • encodedBodySize و decodedBodySize ]: اندازه منبع به شکل رمزگذاری شده یا رمزگشایی شده آن (به ترتیب).
  • transferSize : اندازه منبعی که در واقع از طریق شبکه منتقل شده است. هنگامی که منابع با استفاده از حافظه پنهان تکمیل می شوند، این مقدار می تواند بسیار کوچکتر از encodedBodySize باشد، و در برخی موارد می تواند صفر شود، اگر نیازی به اعتبار سنجی مجدد حافظه پنهان نباشد.

می‌توانید از ویژگی transferSize ورودی‌های زمان‌بندی منبع برای اندازه‌گیری متریک نرخ ضربه حافظه پنهان یا متریک اندازه کل منبع ذخیره‌شده استفاده کنید، که می‌تواند برای درک اینکه چگونه استراتژی ذخیره‌سازی منابع شما بر عملکرد بازدیدکنندگان تکراری تأثیر می‌گذارد، مفید باشد.

مثال زیر تمام منابع درخواست شده توسط صفحه را ثبت می کند و نشان می دهد که آیا هر منبع با استفاده از کش تکمیل شده است یا خیر:

// Catch errors some browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
  // Create the performance observer.
  const po = new PerformanceObserver((list) => {
    for (const entry of list.getEntries()) {
      // If transferSize is 0, the resource was fulfilled via the cache.
      console.log(entry.name, entry.transferSize === 0);
    }
  });
  // Start listening for `resource` entries to be dispatched.
  po.observe({type: 'resource', buffered: true});
} catch (e) {
  // Do nothing if the browser doesn't support this API.
}

پشتیبانی مرورگر

  • 57
  • 12
  • 58
  • 15

منبع

Navigation Timing API شبیه به Resource Timing API است، اما فقط درخواست‌های ناوبری را گزارش می‌کند. نوع ورودی navigation نیز مشابه نوع ورودی resource است، اما حاوی برخی اطلاعات اضافی است که فقط مربوط به درخواست های ناوبری است (مانند زمانی که DOMContentLoaded و رویدادهای load فعال می شوند).

یکی از معیارهایی که بسیاری از توسعه‌دهندگان برای درک زمان پاسخ سرور دنبال می‌کنند، Time to First Byte (TTFB) است که از طریق مهر زمانی responseStart در Navigation Timing API در دسترس است.

// Catch errors since  browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
  // 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});
} catch (e) {
  // Do nothing if the browser doesn't support this API.
}

یکی دیگر از توسعه دهندگان متریکی که ممکن است به آن اهمیت دهند، زمان راه اندازی سرویس دهنده برای درخواست های ناوبری است. این مدت زمانی است که مرورگر برای راه‌اندازی رشته سرویس‌کار قبل از اینکه بتواند رویدادهای واکشی را رهگیری کند، طول می‌کشد.

زمان راه‌اندازی کارگر سرویس برای یک درخواست ناوبری مشخص را می‌توان از دلتای بین entry.responseStart و entry.workerStart به شرح زیر تعیین کرد:

// Catch errors some browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
  // 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});
} catch (e) {
  // Do nothing if the browser doesn't support this API.
}

Server Timing API

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 از APIهای Resource Timeming و Navigation Timing بخوانید.

// Catch errors some browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
  // 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});
} catch (e) {
  // Do nothing if the browser doesn't support this API.
}