ارزیابی عملکرد بارگیری در میدان با زمان‌بندی ناوبری و زمان‌بندی منابع

اصول استفاده از Navigation و Resource Timeming APIها برای ارزیابی عملکرد بارگیری در این زمینه را بیاموزید.

اگر از مهار اتصال در پانل شبکه در ابزارهای توسعه دهنده مرورگر (یا Lighthouse در کروم) برای ارزیابی عملکرد بارگیری استفاده کرده اید، می دانید که این ابزارها برای تنظیم عملکرد چقدر راحت هستند. شما می توانید به سرعت تاثیر بهینه سازی عملکرد را با سرعت اتصال پایه ثابت و پایدار اندازه گیری کنید. تنها مشکل این است که این آزمایش مصنوعی است که داده های آزمایشگاهی را به دست می دهد، نه داده های میدانی .

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

زمان‌بندی ناوبری و زمان‌بندی منابع دو API مشابه با همپوشانی قابل توجهی هستند که دو چیز متمایز را اندازه‌گیری می‌کنند:

  • زمان‌بندی ناوبری سرعت درخواست‌های اسناد HTML (یعنی درخواست‌های ناوبری) را اندازه‌گیری می‌کند.
  • Resource Timeming سرعت درخواست منابع وابسته به سند مانند CSS، جاوا اسکریپت، تصاویر و غیره را اندازه گیری می کند.

این APIها داده های خود را در یک بافر ورود عملکرد ، که می توان در مرورگر با جاوا اسکریپت به آن دسترسی داشت، نشان می دهد. راه های متعددی برای پرس و جو از بافر عملکرد وجود دارد، اما یک راه رایج استفاده از performance.getEntriesByType است:

// Get Navigation Timing entries:
performance.getEntriesByType('navigation');

// Get Resource Timing entries:
performance.getEntriesByType('resource');

performance.getEntriesByType رشته ای را می پذیرد که نوع ورودی هایی را که می خواهید از بافر ورودی عملکرد بازیابی کنید، توصیف می کند. 'navigation' و 'resource' به ترتیب زمان‌بندی را برای APIهای زمان‌بندی ناوبری و زمان‌بندی منابع بازیابی می‌کنند.

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

عمر و زمان درخواست شبکه

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

نمودار زمان‌بندی شبکه همانطور که در DevTools کروم نشان داده شده است. زمان بندی نشان داده شده برای صف درخواست، مذاکره اتصال، خود درخواست و پاسخ در نوارهای رنگی است.
تجسم درخواست شبکه در پانل شبکه DevTools Chrome

عمر درخواست شبکه دارای مراحل مشخصی است، مانند جستجوی DNS، برقراری اتصال، مذاکره TLS و غیره. این زمان‌بندی‌ها به‌عنوان یک DOMHighResTimestamp نشان داده می‌شوند. بسته به مرورگر شما، دانه بندی زمان بندی ممکن است تا میکروثانیه باشد یا تا میلی ثانیه گرد شود. بیایید این مراحل را به تفصیل بررسی کنیم، و چگونگی ارتباط آنها با زمان بندی ناوبری و زمان بندی منابع را بررسی کنیم.

جستجوی DNS

هنگامی که کاربر به یک URL می رود، سیستم نام دامنه (DNS) برای ترجمه یک دامنه به یک آدرس IP پرس و جو می شود. این فرآیند ممکن است زمان قابل توجهی طول بکشد—حتی زمانی که می خواهید در این زمینه اندازه گیری کنید. زمان‌بندی ناوبری و زمان‌بندی منابع دو زمان‌بندی مرتبط با DNS را نشان می‌دهند:

  • domainLookupStart زمانی است که جستجوی DNS آغاز می شود.
  • domainLookupEnd زمانی است که جستجوی DNS به پایان می رسد.

محاسبه کل زمان جستجوی DNS را می توان با کم کردن متریک شروع از متریک پایان انجام داد:

// Measuring DNS lookup time
const [pageNav] = performance.getEntriesByType('navigation');
const totalLookupTime = pageNav.domainLookupEnd - pageNav.domainLookupStart;

مذاکره اتصال

یکی دیگر از عوامل مؤثر در عملکرد بارگذاری، مذاکره اتصال است، که تاخیری است که هنگام اتصال به وب سرور ایجاد می شود. اگر HTTPS درگیر باشد، این فرآیند شامل زمان مذاکره TLS نیز می شود. مرحله اتصال شامل سه زمان بندی است:

  • connectStart زمانی است که مرورگر شروع به باز کردن اتصال به یک وب سرور می کند.
  • secureConnectionStart زمانی را مشخص می کند که مشتری مذاکره TLS را شروع می کند.
  • connectEnd زمانی است که اتصال به وب سرور برقرار شده است.

اندازه‌گیری زمان کل اتصال مشابه اندازه‌گیری کل زمان جستجوی DNS است: زمان شروع را از زمان پایان کم می‌کنید. با این حال، یک ویژگی secureConnectionStart اضافی وجود دارد که در صورت عدم استفاده از HTTPS یا اگر اتصال پایدار باشد، ممکن است 0 باشد. اگر می خواهید زمان مذاکره TLS را اندازه گیری کنید، باید این را در نظر داشته باشید:

// Quantifying total connection time
const [pageNav] = performance.getEntriesByType('navigation');
const connectionTime = pageNav.connectEnd - pageNav.connectStart;
let tlsTime = 0; // <-- Assume 0 to start with

// Was there TLS negotiation?
if (pageNav.secureConnectionStart > 0) {
  // Awesome! Calculate it!
  tlsTime = pageNav.connectEnd - pageNav.secureConnectionStart;
}

هنگامی که جستجوی DNS و مذاکره اتصال به پایان می رسد، زمان بندی مربوط به واکشی اسناد و منابع وابسته به آنها وارد عمل می شود.

درخواست ها و پاسخ ها

عملکرد بارگذاری تحت تأثیر دو نوع عامل است:

  • عوامل بیرونی: اینها مواردی مانند تأخیر و پهنای باند هستند. فراتر از انتخاب یک شرکت میزبان و یک CDN، آنها (بیشتر) خارج از کنترل ما هستند، زیرا کاربران می توانند از هر کجا به وب دسترسی داشته باشند.
  • عوامل درونی: اینها مواردی مانند معماری های سمت سرور و کلاینت و همچنین اندازه منابع و توانایی ما برای بهینه سازی آن چیزهایی هستند که تحت کنترل ما هستند.

هر دو نوع عامل بر عملکرد بارگذاری تأثیر می گذارند. زمان‌بندی‌های مرتبط با این عوامل حیاتی هستند، زیرا توضیح می‌دهند که دانلود چقدر طول می‌کشد. هم زمان‌بندی ناوبری و هم زمان‌بندی منابع، عملکرد بارگیری را با معیارهای زیر توصیف می‌کنند:

  • fetchStart زمانی را علامت گذاری می کند که مرورگر شروع به واکشی یک منبع (Resource Timeming) یا یک سند برای درخواست ناوبری (Navigation Timing) می کند. این قبل از درخواست واقعی است، و نقطه‌ای است که مرورگر در حال بررسی حافظه‌های پنهان (به عنوان مثال، نمونه‌های HTTP و Cache ) است.
  • workerStart زمانی را علامت‌گذاری می‌کند که درخواست در کنترل‌کننده رویداد fetch کارگر خدماتی شروع می‌شود. زمانی که هیچ سرویس دهنده ای صفحه فعلی را کنترل نمی کند، این 0 خواهد بود.
  • requestStart زمانی است که مرورگر درخواست را ارسال می کند.
  • responseStart زمانی است که اولین بایت پاسخ می رسد.
  • responseEnd زمانی است که آخرین بایت پاسخ می رسد.

این زمان‌بندی‌ها به شما امکان می‌دهد جنبه‌های مختلف عملکرد بارگیری را اندازه‌گیری کنید، مانند جستجوی حافظه پنهان در یک سرویس‌کار و زمان دانلود:

// Cache seek plus response time of the current document
const [pageNav] = performance.getEntriesByType('navigation');
const fetchTime = pageNav.responseEnd - pageNav.fetchStart;

// Service worker time plus response time
let workerTime = 0;

if (pageNav.workerStart > 0) {
  workerTime = pageNav.responseEnd - pageNav.workerStart;
}

همچنین می‌توانید جنبه‌های دیگر تأخیر درخواست/پاسخ را اندازه‌گیری کنید:

const [pageNav] = performance.getEntriesByType('navigation');

// Request time only (excluding redirects, DNS, and connection/TLS time)
const requestTime = pageNav.responseStart - pageNav.requestStart;

// Response time only (download)
const responseTime = pageNav.responseEnd - pageNav.responseStart;

// Request + response time
const requestResponseTime = pageNav.responseEnd - pageNav.requestStart;

اندازه گیری های دیگری که می توانید انجام دهید

زمان‌بندی ناوبری و زمان‌بندی منابع برای بیش از آنچه در مثال‌های بالا آمده است مفید است. در اینجا چند موقعیت دیگر با زمان بندی مربوطه وجود دارد که ممکن است ارزش کاوش را داشته باشد:

  • ریدایرکت‌های صفحه: تغییر مسیرها منبع نادیده گرفته‌ای از تأخیر اضافه هستند، به‌ویژه زنجیره‌های تغییر مسیر. تأخیر به روش‌های مختلفی اضافه می‌شود، مانند جهش HTTP به HTTP، و همچنین تغییر مسیرهای 302/301 ذخیره نشده. زمان‌بندی redirectStart ، redirectEnd و redirectCount برای ارزیابی تأخیر تغییر مسیر مفید هستند.
  • بارگیری سند: در صفحاتی که کد را در یک کنترل کننده رویداد unload اجرا می کنند، مرورگر باید آن کد را قبل از رفتن به صفحه بعدی اجرا کند. unloadEventStart و unloadEventEnd تخلیه سند را اندازه گیری می کنند.
  • پردازش سند: زمان پردازش سند ممکن است نتیجه ای نداشته باشد مگر اینکه وب سایت شما بارهای HTML بسیار زیادی ارسال کند. اگر این وضعیت شما را توصیف می‌کند، زمان‌بندی‌های domInteractive ، domContentLoadedEventStart ، domContentLoadedEventEnd و domComplete ممکن است مورد توجه باشند.

دریافت زمان بندی در کد برنامه

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

روش توصیه شده برای جمع آوری ورودی ها از بافر ورود عملکرد استفاده از PerformanceObserver است. PerformanceObserver به ورودی‌های عملکرد گوش می‌دهد و به محض اضافه شدن به بافر، آن‌ها را ارائه می‌کند:

// Create the performance observer:
const perfObserver = new PerformanceObserver((observedEntries) => {
  // Get all resource entries collected so far:
  const entries = observedEntries.getEntries();

  // Iterate over entries:
  for (let i = 0; i < entries.length; i++) {
    // Do the work!
  }
});

// Run the observer for Navigation Timing entries:
perfObserver.observe({
  type: 'navigation',
  buffered: true
});

// Run the observer for Resource Timing entries:
perfObserver.observe({
  type: 'resource',
  buffered: true
});

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

تلفن زدن به خانه

هنگامی که تمام زمان بندی های مورد نیاز خود را جمع آوری کردید، می توانید آنها را برای تجزیه و تحلیل بیشتر به نقطه پایانی ارسال کنید. دو راه برای انجام این کار با navigator.sendBeacon یا fetch با مجموعه گزینه keepalive است. هر دو روش یک درخواست را به یک نقطه پایانی مشخص به روشی غیر مسدود کننده ارسال می‌کنند و در صورت لزوم، درخواست به گونه‌ای در صف قرار می‌گیرد که در صورت لزوم، بیشتر از جلسه صفحه فعلی باقی بماند:

// Caution: If you have lots of performance entries, don't
// do this. This is an example for illustrative purposes.
const data = JSON.stringify(performance.getEntries()));

// The endpoint to transmit the encoded data to
const endpoint = '/analytics';

// Check for fetch keepalive support
if ('keepalive' in Request.prototype) {
  fetch(endpoint, {
    method: 'POST',
    body: data,
    keepalive: true,
    headers: {
      'Content-Type': 'application/json'
    }
  });
} else if ('sendBeacon' in navigator) {
  // Use sendBeacon as a fallback
  navigator.sendBeacon(endpoint, data);
}

در این مثال، رشته JSON به یک بار POST می رسد که می توانید آن را رمزگشایی کرده و در صورت نیاز در یک برنامه کاربردی پردازش/ذخیره کنید.

بسته شدن

هنگامی که معیارها را جمع آوری کردید، این شما هستید که چگونه آن داده های میدانی را تجزیه و تحلیل کنید. هنگام تجزیه و تحلیل داده‌های میدانی، چند قانون کلی وجود دارد که باید از آنها پیروی کنید تا مطمئن شوید که نتیجه‌گیری معنی‌داری دارید:

  • از میانگین‌ها پرهیز کنید ، زیرا نشان‌دهنده تجربه هیچ یک از کاربران نیستند و ممکن است با موارد پرت منحرف شوند.
  • به صدک ها تکیه کنید. در مجموعه داده های معیارهای عملکرد مبتنی بر زمان، کمتر بهتر است. این بدان معناست که وقتی صدک های پایین را اولویت بندی می کنید، فقط به سریع ترین تجربه ها توجه می کنید.
  • دم بلند ارزش ها را اولویت بندی کنید . وقتی تجربیات را در صدک 75 یا بالاتر در اولویت قرار می دهید، تمرکز خود را در جایی قرار می دهید که به آن تعلق دارد: روی کندترین تجربیات.

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

با استفاده از این APIها و داده‌هایی که ارائه می‌کنند، برای درک اینکه چگونه عملکرد بارگیری توسط کاربران واقعی تجربه می‌شود، مجهز خواهید شد، که به شما اطمینان بیشتری در تشخیص و رسیدگی به مشکلات عملکرد بارگذاری در این زمینه می‌دهد.